el-select组件的options条数过多时的解决方案
业务场景当使用el-select组件时,如果options数量过多,会存在的弊端:页面渲染出大量el-option节点,会导致页面卡顿甚至卡死,用户体验极差。选择时条目众多,查找困难。本次我遇到的场景是options数量为6-9千的情况。解决思路从总options中取出固定条目的小option(renderOption)用于页面渲染,利用el-select提供的filter-method方法进行搜
·
业务场景
当使用el-select组件时,如果options数量过多,会存在的弊端:
- 页面渲染出大量el-option节点,会导致页面卡顿甚至卡死,用户体验极差。
- 选择时条目众多,查找困难。
本次我遇到的场景是options数量为6-9千的情况。
解决思路
从总options中取出固定条目的小option(renderOption)用于页面渲染,利用el-select提供的filter-method方法进行搜索过滤,在搜索时用过滤结果更新renderOption。
代码实现
下面是vue的组件封装
<template>
<el-select
class="yt-select"
v-model="currValue"
filterable
v-bind="$attrs"
:filter-method="userFilter"
:disabled="disabled"
:clearable="clearable"
@change="change"
>
<el-option
v-for="option in renderOption"
:key="option.value"
:value="option.value"
:label="option.label"
>{{ option.label }}</el-option>
</el-select>
</template>
<script>
export default {
name: 'easy-select',
props: {
value: {
type: [String, Number],
default: ''
},
max: {
type: Number,
default: 30
},
disabled: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: true
},
options: {
type: Array,
default: () => []
}
},
data () {
return {
renderOption: []
}
},
computed: {
currValue: {
get () {
return this.value || ''
},
set (value) {
this.$emit('input', value)
}
}
},
watch: {
value () {
this.addValueOptions()
},
options: {
handler (V) {
this.init()
},
deep: true
}
},
created () {
this.init()
},
methods: {
async init () {
this.userFilter()
this.addValueOptions()
},
addValueOptions () {
if (this.currValue) {
let target = this.options.find((item) => { // 从大option中找到当前条
return item.value === this.currValue
})
if (target) { // 将当前条与小option比对,没有则加入
if (this.renderOption.every(item => item.value !== target.value)) {
this.renderOption.unshift(target)
}
}
}
},
addFilterOptions (label) {
// 每次查找输入时,若有精确匹配的条目,保证该条目一定在renderOption内
let target = this.options.find((item) => { // 从大option中找到当前条
return item.label === label
})
if (target) { // 将当前条与小option比对,没有则加入
if (this.renderOption.every(item => item.label !== target.label)) {
this.renderOption.unshift(target)
}
}
},
userFilter (query = '') {
let arr = this.options.filter((item) => {
return item.label.includes(query) || item.value.includes(query)
})
if (arr.length > this.max) {
this.renderOption = arr.slice(0, this.max)
this.addFilterOptions(query)
} else {
this.renderOption = arr
}
},
change (value) {
this.$emit('change', value)
if (!value) { // 单选清空-optons初始化下
this.userFilter()
}
}
}
}
</script>
注意事项
- 初始化和value值变化时,需要找到value对应具体项,并加入renderOptions
- 搜索时,可能过滤到的n条数据都没有包含用户想找的具体项,因此,过滤时需要进行一下精确查找,将匹配项放入renderOptions头部
如果您有什么好的思路与建议,欢迎在评论区讨论~
更多推荐



所有评论(0)