背景
常规的下拉框,要么是单选、要么是多选、要么是级联选择。
但是,这些都只是常规的,你永远不知道产品经理是不是常规的!
现在他有个需求,需要做一个下拉框,叫“隐患等级”,里面的选项如下:
现在他想除了全部不支持多选,其他项都支持多选。
我翻译过来就是:
- 点击全部,清空其他选择配【看起来是单选了】
- 点击其他项,如果包含全部这项,则清除全部这项【符合他的需求,
全部项不能多选】
实现过程
假设我声明了一个数组、如下所示:
dangerLevelOptions: [
{ value: '', label: '全部', },
{ value: '1', label: '缺陷', },
{ value: '2', label: '一般隐患', },
{ value: '3', label: '较大隐患', },
{ value: '4', label: '重大隐患', },
{ value: '5', label: '特别重大隐患', },
],
同时写了下拉框,代码如下
<el-form-item label="隐患等级">
<el-select
v-model="searchParams.dangerLevel"
placeholder="隐患等级"
multiple
collapse-tags
style="width: 175px;"
@change="changeLevel"
>
<el-option
v-for="item in dangerLevelOptions"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select>
</el-form-item>
接下来就是监听searchParams.dangerLevel值了,主要在changeLevel方法里处理。
失败一
一开始我在changeLevel方法里监听,我通过判断值是否包含''来判断是否选择了全部
changeLevel(value) {
if (value.includes('')) {
// 如果选择了“全部”,则清空其他选项
this.searchParams.dangerLevel = [''];
} else {
// 如果没有选择“全部”,则移除“全部”
this.searchParams.dangerLevel = value.filter(item => item !== '');
}
}
但是我发现,如果一开始你选择了“全部”,那么就无法选择其他项了,因为searchParams.dangerLevel值始终被置为['']
失败二
后来我就想在watch里监听新旧值的变化、来判断是否选择了全部
watch: {
'searchParams.dangerLevel': {
handler(newVal, oldVal) {
if (newVal.includes('') && !oldVal.includes('')) {
// 如果新值包含“全部”而旧值不包含“全部”,则清空其他选项【说明点击了全部】
this.searchParams.dangerLevel = [''];
} else if (newVal.includes('') && oldVal.includes('')) {
// 如果新值和旧值都包含“全部”,则清除全部【说明原来是全部,又点击其他项】
this.searchParams.dangerLevel = newVal.filter(item => item !== '');
}
},
deep: true
}
},
但是该方法会触发多次,因为你多次改变值了,且可能存在未知的情况,所以该方法也放弃了。
方法三
正当我准备找产品经理打架时,我想先冷静一下,于是我又好好观察了这个下拉框,我发现当前选择的项是数组的最后一项
于是我灵光一现,决定不去打架了,我只需要判断最后一项是否为''就行了。
- 如果是,把
dangerLevel设置为值:[''] - 如果不是,则把
dangerLevel数组清除''
最终代码如下:
changeLevel(value) {
// 当前点击的是value数组的最后一项,判断最后一项是否为“全部”,
// 如果是,则清空其他选项
// 如果不是,则清除全部
if (value[value.length - 1] === '') {
this.searchParams.dangerLevel = [''];
} else if (value[value.length - 1] !== '') {
this.searchParams.dangerLevel = value.filter(item => item !=='');
}
}
总结
东西倒是不难,但是一开始做非常规的还是很抵触的!