需求描述:下拉选框select支持分组(OptionGroup)多选,组内元素只能选择一个,(组外元素支持多选,组内元素支持单选,不支持多选);
解决方案
根据on-select 和on-change返回值不同,并且on-select的返回优先于on-change的返回时间的原理,得到本次选中的元素和本次返回的结果。在根据当前选中的id找到当前元素的兄弟元素,将除自己的兄弟元素从选中的集合中删除,从而达到组内单选的效果;
<Select v-model="runGroupTagList" style="width: 100%;" multiple @on-select="handleRgTagListSelect" @on-change="handleRgTagListChange">
<OptionGroup v-for="item of runGroupTypes" :key="item.pid" :label="item.typeName">
<Option v-for="value in item.childList" :key="value.id" :value="value.id">{{ value.typeName }}</Option>
</OptionGroup>
</Select>
全局变量
// 数据源 childList下的id不会重复,server不区分类别只取ID值
runGroupTypes: [
{
typeName: '团类型',
pid: 0,
childList: [
{id: 20, typeName: '学生团'},
{id: 40, typeName: '财团'},
{id: 10, typeName: '政团'},
{id: 30, typeName: '社团'},
]
},
{
typeName: '团称号',
pid: 1,
childList: [
{id: 50, typeName: '特殊团'},
]
}
],
runGroupTypeId: null, // 当前选择获取的ID
runGroupTagList: [], // 选中元素
选中和改变事件
// on-select的返回优先于on-change的返回
handleRgTagListSelect(obj) {
this.runGroupTypeId = obj.value
},
handleRgTagListChange(value) {
// 根据当前选中的id找到当前元素的兄弟元素,将除自己的兄弟元素从集合中删除,从而达到单选的效果
if (this.runGroupTypeId) {
if (this.runGroupTagList.length > 0) {
let index = this.runGroupTagList.indexOf(this.runGroupTypeId)
if (index > -1) {
// 查找当前选项的父对象
let parentObj = this.runGroupTypes.find( item => {
let child = item.childList.filter(child => child.id === this.runGroupTypeId)
if (child.length) {
return item
}
return null
})
// 根据当前对象的父级筛选出所有的兄弟元素
parentObj && parentObj.childList.forEach(item => {
let idx = this.runGroupTagList.indexOf(item.id)
if (idx >= 0 && item.id !== this.runGroupTypeId ) {
this.runGroupTagList.splice(idx, 1)
}
})
}
}
}
this.runGroupTypeId = null
}