以下方法仅为个人在遇到这种场景的一些个人愚见,如果有更好的方法请大佬赐教。
环境:vue2 + elementui
场景:使用select组件,选项通过接口动态返回,在触发选项展示的时候实时调取接口返回最新的选项,并且当前select组件v-model(对应代码中的selectValue)对应的数据已经存在默认值(或赋值)
<template>
<div>
<el-select
v-model="selectValue"
placeholder="请选择"
filterable
@visible-change="handleChangeSelectVisible"
>
<el-option v-for="item in currentSelectOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
<el-button @click="handleDeleteOption">删除一个选项</el-button>
</div>
</template>
<script>
// 模拟的获取选项的接口,实际为用setTimeout模拟异步的操作
import { getOptions } from "@/utils/mock";
import { cloneDeep } from "lodash"
export default {
name: 'demo',
data() {
return {
selectValue: "",
selectOptions: [
{
label: "option1",
value: "1"
},
{
label: "option2",
value: "2"
},
{
label: "option3",
value: "3"
},
{
label: "option4",
value: "4"
},
{
label: "option5",
value: "5"
},
],
currentSelectOptions: []
}
},
mounted(){
// 加载完成的时候获取一次下拉选项列表
this.getOpt()
// 并且给定第一个选项为默认值
this.selectValue = this.selectOptions[0].value
},
methods: {
async getOpt() {
const res = await getOptions(this.selectOptions)
this.currentSelectOptions = res
},
handleChangeSelectVisible(flag) {
// 此方法传参只返回两种结果:true代表下拉框弹出,false代表下拉框收回,如果不对其进行处理,则会调用两次该方法,我们想要的是在下拉框弹出的时候调取一次获取最新选项的接口,因此当flag为true的时候调用接口
if (flag) {
this.getOpt()
}
},
handleDeleteOption() {
//该方法是为了模拟选项列表中选项被删除的功能
const temp = cloneDeep(this.selectOptions)
temp.pop()
this.selectOptions = temp
}
}
}
</script>
此时,如果删掉选项列表里面的选项(页面操作为点击了删除选项的按钮)
通过网上查到的资料查到这是因为select存在已选值的时候,通过接口更新了选项列表,而select的v-model绑定的值并没有更新,就会出现以上描述的问题。即el-select对应的v-model在el-option中找不到对应的值,就会出现上述错误。
解决方法:
对handleChangeSelectVisible进行改造
data(){
return {
tempSelectValue :"",// 新增用来存储当前select选中的值
}
},
methods:{
handleChangeSelectVisible(flag) {
// 此方法传参只返回两种结果:true代表下拉框显示,false代表下拉框关闭,如果不对其进行处理,则会调用两次该方法
if (flag) {
// 使用变量将原本的值保存进来
this.tempSelectValue = this.selectValue
this.selectValue = ""
this.getOpt()
}else {
// 在下拉框关闭时,需将在下拉框展示时消除的select的v-model对应的值恢复,而此时原本的值可能已经被删除,因此要在最新的选项中查找是否有对应的值,如果有,则恢复,如果没有,则清空
const valueItem = this.currentSelectOptions.find(
(item) => {
return item.value === this.tempSelectValue
}
)
// 这一步是为了避免在下拉框展示的时候已经选了值,如果直接就把变量赋值到v-model对应的值的话,那么这个值将不会根据选择的值而改变,而是会固定为一个特定的值(即使用变量保存的原本的值)
if (!this.selectValue) {
this.selectValue = valueItem ? this.tempSelectValue : "" // 如果满足既没有在下拉框展示的时候选取新值,又在新的下拉选项中找不到原来选中的值,则应该赋值为空
}
}
},
}