el-select二次封装实现可分页加载数据

发布时间:2023年12月20日

使用el-select时一次性渲染几百条数据时会造成页面克顿, 可以通过分页来实现, 这里我用的方式为默认获取全部数据, 然后一次性截取10条进行展示, 滚动条触底后会累加, 大家也可以优化为滚动条触底后发送请求去加载数据

  • 创建自定义指令customizeFocus用户懒加载
    在utils文件夹(大家可自定义)下创建customizeFocus.vue
import Vue from 'vue'

/**
 * 封装el-selectt懒加载指令
 * */
Vue.directive('customizeFocus',{
  bind(el,binding){
    let SELECT_DOM = el.querySelector(
      ".el-select-dropdown .el-select-dropdown__wrap"
    );
    SELECT_DOM.addEventListener("scroll", function () {
      let condition = this.scrollHeight - this.scrollTop <= this.clientHeight;

      if (condition) {
        binding.value();
      }
    });
  }
});
  • 创建select.vue文件用来编写分页加载代码
<template>
    <div>
        <el-select v-model="value1" collapse-tags :multiple="isMultiple" filterable :placeholder="placeholder"
                   v-customizeFocus="lazyloading" @change="submit()">
            <el-option v-for="item in stationOptions" :key="item.id" :label="item.label" :value="item.vBindValue">
                <span style="float: left;padding-right: 30px;">{{ item.label }}</span>
                <span style="float: left;padding-right: 30px;">id:-{{ item.id }}</span>
                <span style="float: right; color: #8492a6; font-size: 13px">{{ item.describe }}</span>
            </el-option>
        </el-select>
    </div>
</template>

<script>
/**
 * cur:每页显示多少条, 默认值: 10, 类型: number
 * stationDataList: 已选择的数据, 默认值: [], 类型: array
 * isMultiple: 是否多选, 默认值: false, 类型: boolean
 * returnValue: 返回值内容, 默认值: 数据id, 类型: string
 * placeholder: 提示, 默认值: 请选择, 类型: string
 * */
export default {
    name: "selectModel",
    data() {
        return {
            value1: null,
            // el-select展示的数据
            stationOptions: [],
            // 全部数据
            stationAll: [],
            // 测点懒加载分页
            stationLazy: {
                startCur: 0,
                // 当前页码数据
                pageNum: 1,
            },
            stationData: this.stationDataList
        }
    },
    props: {
        isMultiple: {
            default: false,
            type: Boolean
        },
        stationDataList: {
            default: Array,
            type: Array
        },
        placeholder: {
            default: '请选择',
            type: String
        },
        returnValue: {
            default: 'id',
            type: String
        },
        cur: {
            default: 10,
            type: Number
        }
    },
    mounted() {
        this.getStationAll();
    },
    methods: {
        /**
         * 获取全部测点数据
         * */
        getStationAll() {
        	let returnValue = this.returnValue;
        
            for (let i = 0; i < 100; i++) {
                let obj = {
                    label: 'test_tag' + i+1,
                    id: i+1,
                    describe: 'test_tag' + i+1 + '描述'
                };
                this.stationAll.push(obj);
            }

			// 设置el-option的value绑定值
            if (this.stationAll && this.stationAll.length){
                this.stationAll.forEach(item=>{
                    item['vBindValue'] = item[returnValue]
                })
                
				this.stationOptions = this.stationAll.slice(this.stationLazy.startCur, this.cur);
	
	            // 查看
	            this.matchingData();
            }
            
        },

        /**
         * 匹配stationData里的数据,将其显示到下拉列表中
         * */
        matchingData(){
            if (this.stationData && this.stationData.length){
                this.value1 = [];
                let returnValue = this.returnValue;
                // 1.先查看当前显示的option里是否存在,如果不存在,从全部数据里获取
                this.stationData.forEach(eachItem=>{
                    let stationIndex = this.stationOptions.map(mapItem=>mapItem[returnValue]).indexOf(eachItem);
                    if (stationIndex !== -1){
                        this.value1.push(this.stationOptions[stationIndex][returnValue]);
                    } else {
                        let stationAllIndex = this.stationAll.map(mapItem=>mapItem[returnValue]).indexOf(eachItem);
                        if (stationAllIndex !== -1){
                            this.stationOptions.push(this.stationAll[stationAllIndex]);
                            this.value1.push(this.stationAll[stationAllIndex][returnValue]);
                        }
                    }
                })
            }
        },

        /**
         * 滚动条触底时触发此方法
         * */
        lazyloading() {
            if (this.stationAll.length > 0){
                // 计算总数据共有多少页
                let total = Math.ceil(this.stationAll.length / this.cur);
                // 如果计算总页码数小于等于当前页码数证明已到最后一页
                if (total <= this.stationLazy.pageNum){
                    return console.log('已加载全部数据');
                }

                this.stationLazy.pageNum ++;
                this.stationOptions = this.stationAll.slice(this.stationLazy.startCur, this.cur * this.stationLazy.pageNum);
                this.matchingData();
            }
        },

        /**
         * 提交
         * */
        submit(){
            this.stationData = JSON.parse(JSON.stringify(this.value1));
            this.$emit('callBackData',this.stationData)
        },
    }
}
</script>

<style scoped>

</style>
  • 在主文件里使用,
<template>
  <div>
    <selectModel :stationDataList="stationDataList" v-if="stationDataList.length" :isMultiple="true" @callBackData="callBackData"></selectModel>
  </div>
</template>

<script>
  import selectModel from '../../components/select/index'
  export default {
    name: "index",
    components:{
      selectModel
    },
    data(){
      return {
        stationDataList: [1,2,3,50,100], // 模拟获取出来的数据,数据id
      }
    },
    mounted(){
    },
    methods:{
        /**
         * 返回值
         * */
        callBackData(e){
            console.log(e,'eeeeeeeeeee')
        }
    }
  }
</script>

<style scoped>

</style>
文章来源:https://blog.csdn.net/weixin_40923558/article/details/135091556
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。