最近遇到一个问题,在开发编辑页面时候,遇到select
大数据量,一个下拉选择器有两万个备选,页面上会不定出现3-18个select
,预计可能会渲染30万
多个option
备选,这么多dom加载,直接把浏览器干无响应了。
第一个构想就是
虚拟select
搜索一番没有合适的轮子,vxe-table 比较合适,但是为了一个问题单独引入,不合适,
只能先基于elementUI
的select
选择器再度封装解决问题,节流版select
第一版,节流select
此版本的select规避页面一打开,就加载所有option
导致页面卡死,无法使用为目标
<throttling-select v-model="value" :list="options" :placeholder="placeholder" selkey="key" sellabel="label"></throttling-select>
在vue组件挂载的时候,判断当前select
的option
数量是否超过1000个,小于则直接渲染,大于则不渲染只启用搜索渲染,借助于el-select
的远程搜索功能实现
<template>
<el-select
@visible-change="popChange"
v-model="selectValue"
filterable
remote
:placeholder="placeholder"
:remote-method="remoteMethod"
:loading="loading"
style="width: calc(98% - 20px)"
>
<el-option
v-for="item in options"
:key="item[selkey]"
:label="item[sellabel]"
:value="item[selkey]"
>
</el-option>
</el-select>
</template>
<script>
export default {
mixins: [],
filters: {
},
components: {
},
model: {
prop: 'value', //绑定的值,通过父组件传递
event: 'update' //自定义名
},
props: {
value: {
type: [String, Number],
default: ''
},
list: {
//选项值
type: Array,
default: () => []
},
placeholder: {
type: [String, Number],
default: '选项多,加载慢,建议搜索'
},
selkey: {
type: [String, Number],
default: 'key'
},
sellabel: {
type: [String, Number],
default: 'label'
}
},
data() {
return {
options: [],
selectValue: '',
loading: false
}
},
computed: {
},
watch: {
selectValue(val) {
console.log(val)
this.$emit('update', val)
}
},
created() {
this.selectValue = this.value
},
mounted() {
},
destroyed() {
},
methods: {
popChange(e) {
console.log(e)
if (e) {
this.loading = true
this.options = this.list.length > 1000 ? [] : [...this.list]
this.loading = false
}
},
remoteMethod(query) {
console.log(query)
if (query !== '') {
this.loading = true
this.options = []
const reg = new RegExp(query.toLowerCase())
setTimeout(() => {
this.options = this.list.filter(item => {
return reg.test(item[this.selkey].toLowerCase())
})
this.loading = false
}, 50)
} else {
this.options = []
}
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped></style>
第二版:虚拟select滚动
基于vue-virtual-scroller
插件二次开发,好处是支持大数据,复用dom元素,拖动流畅
虽然作者 已经封装过virtual-selector
插件,但是根本还是在virtual-scroller
上做的二次封装,只完成了最基本的select
功能,定制化不高.
索性自己重新封装,满足自由度。样式嫌丑
或者功能不满足
请自己改virtualSelector.vue
文件
安装
npm install -save vue-virtual-scroller
创建
virtualSelector.vue
文件
//virtualSelector.vue
//开发插件
<template>
<div
class="virtual-selector"
:id="vsId"
>
<span
class="virtual-selector__label"
:class="{none: !label}"
>{
{
label }}</span>
<div class="virtual-selector__input-wrapper">
<input
class="virtual-selector__input"
:placeholder="placeholder"
v-model="selected[option.itemNameKey]"
@keyup="handleKeyup"
@input="handleInput"
@focus="handleFocus($event)"
@select="handleInputSelect($event)"
/