需求:
前面下拉框选择某个选项(如:1)了,
后面的下拉框不能在有前面选中内容的该选项(即不能在出现1的下拉选项)
【Vue 实现动态循环出的多个select 不能重复选择相同的数据】
注:下面注释的都可以根据需求更改
代码
<template> <div id="app"> <div v-for="(item,index) in selectList" :key="index"> <Select v-model="item.value" style="width:200px"> <Option v-for="it in showCityList(item.value)" :value="it.value" :key="it.value" >{{ it.label }}</Option> </Select> <Button icon="md-add-circle" @click="listAdd()"></Button> <Button icon="md-trash" @click="listDelete()"></Button> </div> </div> </template>
测试数据
data() {
return {
selectList: [{ value: "" }],
cityList: [
{
value: "New York",
label: "New York"
},
{
value: "London",
label: "London"
},
{
value: "Sydney",
label: "Sydney"
},
{
value: "Ottawa",
label: "Ottawa"
},
{
value: "Paris",
label: "Paris"
},
{
value: "Canberra",
label: "Canberra"
}
]
};
},
事件
methods: { listAdd() { if (this.selectList.length < this.cityList.length) { this.selectList.push({ value: "" }); } else { console.log("不能再加啦"); } }, listDelete(index) { this.selectList.splice(index, 1); } },
实现部分:
computed: {
showCityList() {
return (val) => {
//讲option的显示数据进行深拷贝
let newList = JSON.parse(JSON.stringify(this.cityList));
//处理selectList数据,返回一个新数组arr
//arr数组就相当于所有Select选中的数据集合(没有选中的为'',不影响判断),只要在这个集合里面,其他的下拉框就不应该有这个选项
const arr = this.selectList.map(item => {
//将其格式{value:'NewYork'}变成['NewYork'],方便使用indexOf进行判断
return (item = item.value);
});
//过滤出newList里面需要显示的数据
newList = newList.filter(item => {
//当前下拉框的选中的数据需要显示
//val就是当前下拉框选中的值
if (val == item.value) {
return item;
} else {
//再判断在arr这个数组中是不是有这个数据,如果不在,说明是需要显示的
if (arr.indexOf(item.value) == -1) {
return item;
}
}
});
//返回Options显示数据
return newList;
};
}
}
在整个showCityList中,唯一的变量就是selectList,只要selectList的值有改变,就会触发计算属性的重新计算,这样就可以保证无论是Select选中某个选项,还是增加下拉框,或者删除下拉框都会让每个下拉框对应的Option中的newList进行重新生成,从而达到多个select不能重复选择相同数据的功能。
———————————————————————————————————————————————————————————————————————————————
Vue 3 实现代码:
<div v-for="(item, index) in tableData.list" class="form-div"> <Row :gutter="10"> <Col :span="6"> <FormItem :name="['list', index, 'temqProjectid']" :rules="[{ required: true, message: '请选择项目', trigger: 'change' }]" > <Select v-model:value="item.temqProjectid" style="width: 100%" :showSearch="true" allow-clear placeholder="请选择项目" > <SelectOption v-for="it in showCityList(item.temqProjectid)" :value="it.value" :key="it.value" >{{ it.label }}</SelectOption > </Select> </FormItem> </Col> </Row> </div> const selectList = ref([{ value: '' }]); // [{ value: '' }]; let cityList = [ { value: 'New York', label: 'New York', }, { value: 'London', label: 'London', }, { value: 'Sydney', label: 'Sydney', }, { value: 'Ottawa', label: 'Ottawa', }, { value: 'Paris', label: 'Paris', }, { value: 'Canberra', label: 'Canberra', }, ]; const showCityList = (val) => { //讲option的显示数据进行深拷贝 let newList = JSON.parse(JSON.stringify(cityList)); //alert(val); //处理selectList数据,返回一个新数组arr //arr数组就相当于所有Select选中的数据集合(没有选中的为'',不影响判断),只要在这个集合里面,其他的下拉框就不应该有这个选项 // const arr = selectList.value.map((item) => { // //将其格式{value:'NewYork'}变成['NewYork'],方便使用indexOf进行判断 // return (item = item.value); // }); const arr = tableData.value.list.map((item) => { //将其格式{value:'NewYork'}变成['NewYork'],方便使用indexOf进行判断 return (item = item.temqProjectid); }); //alert(index + '>>' + val + '>>arr>>' + JSON.stringify(arr)); //过滤出newList里面需要显示的数据 newList = newList.filter((item) => { //当前下拉框的选中的数据需要显示 //val就是当前下拉框选中的值 if (val == item.value) { return item; } else { //再判断在arr这个数组中是不是有这个数据,如果不在,说明是需要显示的 if (arr.indexOf(item.value) == -1) { return item; } } }); //返回Options显示数据 return newList; };
若下拉框未显示文本,显示了值,可以调整如下:
<Select v-model:value="item.temqProjectid" :options="showCityList(item.temqProjectid)" :showSearch="true" style="width: 100%" allow-clear placeholder="请选择项目" />