在前端开发中,字典选择器是一种常见的需求。无论是单选、多选还是下拉选择,开发者都需要一种通用且灵活的方式来处理这些场景。本文将介绍一个名为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>
注意事项
- 字典数据来源:确保后端接口返回的数据格式符合组件要求,例如包含
value
和text
字段。 - 性能优化:对于频繁使用的字典数据,建议启用缓存机制以减少不必要的接口调用。
- 国际化支持:组件中的占位符文本(如
请选择
)可以通过$t
方法实现国际化。
总结
JDictSelectTag
组件以其灵活性和易用性,成为字典选择场景的理想解决方案。无论是简单的单选还是复杂的多选,它都能轻松应对。希望本文能帮助你更好地理解和使用这个组件!