如果有同学还没用过这个功能,可以先了解下:
使用场景
大部分情况下使用 el-select 的时候,el-options 中 options 的值都是后端接口给的数据,直接赋值就可以了。但是有的时候数据量比较大,比如几千甚至上万条的时候,如果直接赋值,整个页面的 dom 会被撑爆,不仅请求全量数据接口的时候时间会很久,而且赋值完之后整个页面会非常卡。
解决方法
现在的 elementPlus 已经有虚拟化选择器了,直接使用,非常方便,如果你使用的是Vue3,可以直接移步 elementPlus官方文档
如果你使用的是 Vue2,很可惜没有现成的组件能够使用。解决方法一共两个,都是需要后端配合前端进行修改的:
- 后端将接口改为分页的形式;前端将选择器下拉框中的数据改为滚动加载
- 后端将接口改为模糊搜索的形式,通过选择器中输入的内容去搜索模糊匹配的数据然后返回;前端使用
elementUI 中选择器的远程搜索功能,用户在选择器输入内容后才发起请求
本次主要讲解使用远程搜索来解决的方法,前端代码就直接放出了,不过多解释:
<el-select ref="selectDom" v-model="form.diagnosisIds" :remote-method="remoteMethod" placeholder="请选择" clearable filterable multiple remote @visible-change="templateTagChange">
<el-option
v-for="item in relationList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<script>
export default {
data: {
return {
form: {
diagnosisIds: []
},
relationList: []
}
},
methods: {
remoteMethod(query) {
if (query !== '') {
this.relationList = []
this.loading = true
getDiagnoseInfo({ diagnoseName: query }).then(res => {
this.loading = false
this.relationList = res.filter(item => {
return item.name.toLowerCase()
.indexOf(query.toLowerCase()) > -1
})
})
} else {
this.relationList = []
}
},
templateTagChange(val) {
if (val === false) {
this.relationList = []
}
}
}
}
</script>
带来的问题
之前直接赋值选择器选项的时候,因为页面加载完选择器的选项就有内容了,所以数据回显的时候一般后端返回id,选择器会自动匹配选项中那一项id对应的name值并回显。但是现在使用远程搜索,页面刚加载完用户不在选择器输入的话,选择器选项一直都是空的,自然也无法进行匹配回显。你会发现这时候只是id回显到选择器中,并不是回显id所匹配的name。那么该怎么解决呢?
如何解决回显问题
首先需要后端配合改一下接口,原本的接口是返回id的字符串,现在需要后端那边匹配一下对应id的name,然后返回id与name的集合,形如 { id: 1, name: 'xxx' } ;然后前端这里有两种解决方法:
1. 给选择器选项赋值
既然是因为选择器选项为空无法进行匹配回显,那就在页面加载完后给选择器选项赋值就好了:
const ids = []
const strs = []
res.tagMapList.forEach(ele => {
ids.push(ele.id)
strs.push(ele.value)
})
for (let i = 0; i < strs.length; i++) {
this.form.diagnosisIds.push(ids[i])
this.relationList.push({
id: ids[i],
name: strs[i]
})
效果如下: 会发现确实成功回显name了,但是当鼠标聚焦在选择器上且未发起远程搜索时,这个下拉框会出现这几项的值(理所应当的问题,因为给选项赋了这几个值嘛,但是在未发起远程搜索之前是不需要这个下拉框的)
2. 使用源码中的 cachedOptions 方法隐藏下拉框中的内容
有兴趣的可以自行查阅elementUI这部分的源码,简而言之就是源码中是利用cachedOptions 方法将当前的下拉选项隐匿储存的集合,那我们可以通过在这个集合中把我们需要显示的选项添加进去
放出代码:
const ids = []
const strs = []
res.tagMapList.forEach(ele => {
ids.push(ele.id)
strs.push(ele.value)
})
for (let i = 0; i < strs.length; i++) {
this.form.diagnosisIds.push(ids[i])
this.$refs.selectDom.cachedOptions.push({
currentLabel: strs[i],
currentValue: ids[i],
label: strs[i],
value: ids[i]
})
}
效果如下:
搞定 ~
参考资料:vue element Select组件远程搜索绑定值为对象时,编辑状态如何回显显示正确的label
|