持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
前言
最近在写一个表单页面,需要使用到el-select
,然后使用了index做key,遇到了问题,通过这篇文章记录下。
问题描述
正常我们使用el-select
,是使用index做key是没有问题的,比如:
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="(item,i) in options"
:key="i"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
data () {
return {
options: [{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶'
}],
value: ''
}
}
这样使用是没有问题的,因为你并没有对options做增加或者删除的操作。就不会影响到options重新渲染的问题。
但是我们这边有个需求,需要支持搜索,而且需要支持可以搜label,也可以搜value。
我们都知道,el-select
有个filterable
属性,但是只支持搜索label。所以我们得另辟蹊径。
继续看文档,我们看到有个filter-method
方法
它配合filterable
一起使用,当你搜索的时候,会触发filter-method
方法,然后把搜索的内容当作参数传入。
所以,我们可以通过自定义搜索方法来实现。
我们需要先定义个源数据sourceOptions
和展示的options
,然后在filter-method
方法对源数据进行过滤,赋值给options
。
代码如下:
<template>
<el-select
v-model="value"
filterable
placeholder="请选择"
:filter-method="filterMethod">
<el-option
v-for="(item,i) in options"
:key="i"
:label="item.label"
:value="item.value"></el-option>
</el-select>
</template>
<script>
export default {
data () {
return {
value: '',
options: [],
sourceOptions: [{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶'
}, {
value: '选项3',
label: '蚵仔煎'
}],
}
},
methods: {
filterMethod (query) {
this.options = this.sourceOptions.filter(item =>
item.label.includes(query) || item.value.includes(query)
)
}
},
mounted () {
this.options = this.sourceOptions
}
}
</script>
没花多少时间就写好了,但是一测试,就发现问题了。
输入“双”的时候,option是正常的,只过滤出双皮奶这个选项。但是,输入框的value被清空了。
我一开始以为filter-method
的方法有问题,但是官方例子却没有问题。
那就奇了怪了。
思索无果,对比了二者代码,才发现,原来我是用了index
做key,而官方文档使用了value
做key。
顿时恍然大悟。
因为vue是使用key来决定是否渲染元素的,如果key是一样的,就会复用,不一样就会重新渲染。
因为我这里使用了index
做key。导致了输入“双”的时候,双皮奶排第一了,index为0。vue认为和没输入时的index=0(黄金糕)是一样的,组件会复用。
但是因为option的value不一样,导致触发了value的watch。
源码的option.vue
, 触发了select组件的setSelected
的方法。
此时this.value
是空字符串,导致this.selectedLabel
也是空字符串。导致输入框的value被清空了。
最终我换成value做key就正常了。组件会复用,而且option的value是一样的,所以它不会触发了value的watch。
代码如下:
<el-select
v-model="value"
filterable
placeholder="请选择"
:filter-method="filterMethod">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
切记:如果你的options可能会改变的时候,不要用index做key。