由于 vue-cli3对node_moudules的处理和 vue-cli2不同, 我们通过将node_moudules中的el-select组件复制到本地, 并扩充组件功能从而实现el-select下拉加载在vue-cli3变得不太现实。如果出现数据量过多(超过3000条), 页面整体会变得卡顿, 用户体验度极差。 这时对el-select组件数据的处理变得极其重要!
解决方法 1: 接口角度上, 接口加筛选条件,对输入内容进行筛选(后台搜索, element-ui有具体说明)。但是假如, 筛选后数据量依旧很大, 仍会出现这种问题, 所以element-ui上的方法不推荐照抄使用。需要做进一步处理。 解决问题, 我们要知道问题原因所在, 页面卡顿原因无非由于直接把所有数据一次性渲染到 el-option上 ,知道了这个, 解决起来就简单多了。 我们可以将从接口获取的数据,分批处理 。
以下为组件
<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>