0
点赞
收藏
分享

微信扫一扫

JDictSelectTag:一个灵活的字典选择组件

嚯霍嚯 03-19 15:00 阅读 17

在前端开发中,字典选择器是一种常见的需求。无论是单选、多选还是下拉选择,开发者都需要一种通用且灵活的方式来处理这些场景。本文将介绍一个名为JDictSelectTag的Vue组件,它能够满足多种字典选择的需求。

组件概述

JDictSelectTag是一个基于Ant Design Vue的字典选择组件,支持以下几种类型的选择器:

  • Radio:单选按钮组
  • Checkbox:复选框组
  • RadioButton:带样式的单选按钮组
  • Select:下拉选择框

通过动态配置tagType属性,可以轻松切换不同的选择器类型。

<template>
  <a-radio-group v-if="tagType == 'radio'" @change="handleInput" :value="getValueSting" :disabled="disabled">
    <a-radio v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio>
  </a-radio-group>
  <a-checkbox-group v-else-if="tagType == 'check'" @change="handleInput" :value="getValueSting" :disabled="disabled"  >
    <a-checkbox v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-checkbox>
  </a-checkbox-group>
  <a-radio-group v-else-if="tagType == 'radioButton'" buttonStyle="solid" @change="handleInput" :value="getValueSting" :disabled="disabled">
    <a-radio-button v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio-button>
  </a-radio-group>
  <a-select
    v-else-if="tagType == 'select'"
    :getPopupContainer="getPopupContainer"
    :placeholder="placeholder"
    :disabled="disabled"
    :value="getValueSting"
    @change="handleInput"
    show-search
    :filterOption="filterOption"
    :optionFilterProp="'text'"
  >
    <a-select-option :value="undefined">{{ $t('TtNoticeList.pleaseSelect') }}</a-select-option>
    <a-select-option v-for="(item, key) in dictOptions" :key="key" :value="item.value">
      <span style="display: inline-block; width: 100%" :title="item.text || item.label">
        {{ item.text || item.label }}
      </span>
    </a-select-option>
  </a-select>
</template>

<script>
import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'

export default {
  name: 'JDictSelectTag',
  props: {
    dictCode: String,
    placeholder: String,
    triggerChange: Boolean,
    disabled: Boolean,
    value: [String, Number],
    type: String,
    getPopupContainer: {
      type: Function,
      default: (node) => node.parentNode,
    },
  },
  data() {
    return {
      dictOptions: [],
      tagType: '',
    }
  },
  watch: {
    dictCode: {
      immediate: true,
      handler() {
        this.initDictData()
      },
    },
  },
  created() {
    // console.log(this.dictCode);
    if (!this.type || this.type === 'list') {
      this.tagType = 'select'
    } else {
      this.tagType = this.type
    }
    //获取字典数据
    // this.initDictData();
  },
  computed: {
    getValueSting() {
      if(this.type=='check'){
        return this.value != null ? this.value.split(',') : []
      }
     
      return this.value != null ? this.value.toString() : undefined
      
    },
  },
  methods: {
    initDictData() {
      //优先从缓存中读取字典配置
      if (getDictItemsFromCache(this.dictCode)) {
        this.dictOptions = getDictItemsFromCache(this.dictCode)
        return
      }

      //根据字典Code, 初始化字典数组
      ajaxGetDictItems(this.dictCode, null).then((res) => {
        if (res.success) {
          //                console.log(res.result);
          this.dictOptions = res.result
        }
      })
    },
    filterOption(input, option) {
      let componentOptions = option.componentOptions
      if (componentOptions.children[0].text == '请选择') {
        return false
      } else {
        let children = componentOptions.children[0].children[0]
        return children.text.toLowerCase().indexOf(input.toLowerCase()) >= 0
      }
    },
    handleInput(e) {
      let val
      if (this.tagType == 'radio') {
        val = e.target.value
      } else if(this.tagType == 'check'){
        val = e.join(',')
      }else{
        val = e
      }
      if (this.triggerChange) {
        this.$emit('change', val)
      } else {
        this.$emit('input', val)
      }
    },
    setCurrentDictOptions(dictOptions) {
      this.dictOptions = dictOptions
    },
    getCurrentDictOptions() {
      return this.dictOptions
    },
  },
}
</script>

核心功能

1. 动态加载字典数据

组件通过dictCode属性指定字典编码,并从后端接口或缓存中加载对应的字典数据。具体逻辑如下:

  • 首先尝试从缓存中读取字典数据(getDictItemsFromCache)。
  • 如果缓存中不存在,则调用ajaxGetDictItems方法从后端获取数据。

initDictData() {
  if (getDictItemsFromCache(this.dictCode)) {
    this.dictOptions = getDictItemsFromCache(this.dictCode);
    return;
  }
  ajaxGetDictItems(this.dictCode, null).then((res) => {
    if (res.success) {
      this.dictOptions = res.result;
    }
  });
}

2. 支持多种选择器类型

根据tagType属性的不同值,组件会渲染相应的选择器:

  • radio:单选按钮组
  • check:复选框组
  • radioButton:带样式的单选按钮组
  • select:下拉选择框

<template>
  <a-radio-group v-if="tagType == 'radio'" />
  <a-checkbox-group v-else-if="tagType == 'check'" />
  <a-radio-group v-else-if="tagType == 'radioButton'" buttonStyle="solid" />
  <a-select v-else-if="tagType == 'select'" />
</template>

3. 自定义事件处理

组件通过handleInput方法处理用户输入事件,并根据triggerChange属性决定是否触发change事件或input事件。

handleInput(e) {
  let val;
  if (this.tagType == 'radio') {
    val = e.target.value;
  } else if (this.tagType == 'check') {
    val = e.join(',');
  } else {
    val = e;
  }
  if (this.triggerChange) {
    this.$emit('change', val);
  } else {
    this.$emit('input', val);
  }
}

使用示例

以下是如何在项目中使用JDictSelectTag组件的示例代码:

<template>
  <div>
    <JDictSelectTag 
      :dictCode="'gender'" 
      :type="'radio'" 
      @change="onGenderChange" 
    />
    <JDictSelectTag 
      :dictCode="'status'" 
      :type="'select'" 
      :placeholder="'请选择状态'" 
    />
  </div>
</template>

<script>
import JDictSelectTag from '@/components/dict/JDictSelectTag.vue';

export default {
  components: { JDictSelectTag },
  methods: {
    onGenderChange(value) {
      console.log('Selected gender:', value);
    },
  },
};
</script>

注意事项

  1. 字典数据来源:确保后端接口返回的数据格式符合组件要求,例如包含valuetext字段。
  2. 性能优化:对于频繁使用的字典数据,建议启用缓存机制以减少不必要的接口调用。
  3. 国际化支持:组件中的占位符文本(如请选择)可以通过$t方法实现国际化。

总结

JDictSelectTag组件以其灵活性和易用性,成为字典选择场景的理想解决方案。无论是简单的单选还是复杂的多选,它都能轻松应对。希望本文能帮助你更好地理解和使用这个组件!

举报

相关推荐

0 条评论