问题描述:
最近项目中,表单中有需要选择公司联系人的下拉框,由于人员过多,选择的时候会因为数据量过大导致页面卡顿,于是对于el-select进行二次封装
解决方案:
* remote-method:远程搜索方法
* visible-change:下拉框出现/隐藏时触发
1、对返回数据进行切割,使用visible-change,在下拉框出现时默认显示100条数据;
2、使用remote-method远程方法进行搜索;
3、搜索时,将已经选择的数据合并到搜索列表中,防止因列表匹配不到显示成ID;
4、创建 el-select-loadmore 指令方法进行滚动加载;
5、使用 @input="$emit('input',$event)" 进行双向绑定
实现方式:
1、在main.js中创建滚动指令 el-select-loadmore
// 下拉列表 Vue.directive( 'el-select-loadmore', { bind(el, binding) { let self =
this // 获取element-ui定义好的scroll盒子 const SELECTWRAP_DOM =
el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
SELECTWRAP_DOM.addEventListener('scroll', function () { /** * scrollHeight
获取元素内容高度(只读) * scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条,
那它的scrollTop的值默认为0. * clientHeight 读取元素的可见高度(只读) * 如果元素滚动到底, 下面等式返回true,
没有则返回false: * ele.scrollHeight - ele.scrollTop === ele.clientHeight; */ const
condition = this.scrollHeight - this.scrollTop <= this.clientHeight; if
(condition) binding.value() }); } } )
2、创建componentPeople.vue组件文件
<template> <el-select :value="value"
v-el-select-loadmore:rangeNum="loadMore(rangeNumber)" @change="getChange"
@input="$emit('input',$event)" :loading="loading" :multiple="multiple"
reserve-keyword clearable :disabled="selectDisabled" :remote-method="(query) =>
{remoteMethod(query, value)}" filterable placeholder="输入姓名进行匹配" remote
:size="selectSize" style="width: 100%" @visible-change="visibleChange" >
<el-option v-for="item in originalOptions.slice(0, rangeNumber)"
:key="item.userId" :label="item.username" :value="item.userId" /> </el-select>
</template> <script> export default { name: "componentPeople", props: {
//组件size selectSize: { type: String, default: 'medium' }, //组件options options:
{ type: Array, default: () => { return [] } }, //传入的数据 value: { type: [String,
Number, Array], }, //是否多选 multiple: { type: Boolean, default: false }, //是否禁用
selectDisabled: { type: Boolean, default: false } },
//使用监听器监听传入的options,赋值给originalOptions watch: { options: { handler(val) {
console.log(val); this.originalOptions = val }, deep: true },
//监听所选项变化,进行搜索回显/或初始化列表数据并回显 value(val) { this.remoteMethod(this.text,val) },
}, data() { return{ text: '', //默认搜索项 loading: false, //搜索loading rangeNumber:
100, //默认显示列表数量 originalOptions: [],//下拉列表数据 } }, methods: { //
下拉框显示/隐藏触发,下来框显示初始话值为100 visibleChange(flag) { if (flag) { this.rangeNumber =
100 } }, //远程搜索方法 remoteMethod(query, checkedData) { this.text = query
this.loading = true; setTimeout(() => { this.loading = false; //从完整数据中筛选所匹配项
let arr = this.options.filter(item => { return
item.username.toLowerCase().indexOf(query.toLowerCase()) > -1; });
//获取已经选择的数据防止因数据初始化匹配不到显示为ID let initUserList = !!checkedData ?
this.initUserSelectData(checkedData) : [] //删除搜索列表相同ID,并重新赋值
this.originalOptions = [...initUserList, ...arr.filter(item =>
!initUserList.some(x => x.userId === item.userId ))] }, 80); }, //
解决回显时显示为id的问题 initUserSelectData(arr) { //获取当前所选值 if (this.multiple) { return
this.options.filter(item => arr.some(x => x === item.userId)); // 选中的值 数组 }
return this.options.filter(item => arr === item.userId); // 选中的值 数组 }, //
下拉框滚动触发添加待选数据 loadMore(n) { //n是默认初始展示的条数会在渲染的时候就可以获取,具体可以打log查看 return () =>
this.rangeNumber += 10 //每次滚动到底部可以新增条数 可自定义 }, getChange(val) {
this.$emit('getChange', val) }, }, mounted() { this.originalOptions =
this.options } } </script> <style scoped> </style>
3、在页面中使用
<component-people v-model="formDta.name" :options="options" selectSize="mini"
:multiple="true" ></component-people>
完结撒花0.0.