select 组件在几千上万条数据的时候特别卡,调试发现option组件渲染太多,导致整个页面都卡,通过调研发现可以通过虚拟加载的方式动态渲染option,亲测上万数据一点都不卡,废话不说,上代码
虚拟加载用的是 vue-virtual-scroller 具体怎么安装和使用,这就不介绍,网上一大把,下面是select结合 vue-virtual-scroller 的代码,由于option上包了一成代码,会导致select选中的样式不会自动加上,需要手动在option上加上选中样式
<Select v-model="nodeData.fileUniqueList" multiple filterable filter-by-labelref="select"@on-query-change="fileQueryChange"style="width:100%"><recycle-scrollerclass="virtual-list":buffer="200":prerender="10"style="height: 180px":item-size="30"key-field="value":items="fileList"><template v-slot="{ item, index }"><Option:class="{'ivu-select-item selected':nodeData.fileUniqueList.includes(item.value)}":value="item.value" :key="item.value" :label="item.fileName">{{ item.fileName }}</Option></template></recycle-scroller></Select>
在 mounted 中把select的自动过滤方法重写,这一步很关键,没这一步会导致搜索的option被强制重写,这样永远都渲染不出来数据
this.$nextTick(() => {// 替换过滤函数this.$refs.select.validateOption = () => true;});
然后就是自定义查询方法,通过 on-query-change事件自己写过滤方法,我这是先把查出来的数据备份了一份,然后在备份的数据里面查找在深度拷贝给对象
fileQueryChange(v) {if (v) {let data = deepClone(this.fileListBak.filter(f => f.fileName.indexOf(v) >= 0))this.fileList = data} else {this.fileList = deepClone(this.fileListBak)}},
最后就是返现问题,由于动态渲染不会把所有的option都渲染出来,导致不能返现,调试了下发现多选的时候,select组件是在values里面plus值,所以在数据返回后,循环以前选中的,然后查找,最后给values赋值,这是多选的方式,单选应该也是大同小异,如果不行,去调试一下看单选是怎么赋值的
this.$refs.select.values = []this.nodeData.fileUniqueList.forEach(f => {let data = this.fileList.find(d => d.value == f)this.$refs.select.values.push({label: data.fileName,tag: undefined,value: f})})