el-select滚动分页加载、模糊搜索

大部分情况下使用 el-select 的时候,el-options 中 options 的值都是后端接口给的数据,直接赋值就可以了。但是有的时候数据量比较大,比如几千甚至上万条的时候,如果直接赋值,整个页面的 dom 会被撑爆,不仅请求全量数据接口的时候时间会很久,而且赋值完之后整个页面会非常卡。
解决方案:
        我们可以实现一个Vue的自定义指令,每当使用el-select滚动到列表底部的时候就请求下一页数据,来达到下拉滚动加载更多的目的。并将其封装为一个组件,使用时调用父组件传入下拉列表的内容,并在选中数据时回传选中的数据。

1.封装触底自定义指令

src/plugins/select目录下创建 select.js,并在main.js中全局引入
代码主要是实现一个el-select下拉加载的自定义指令v-loadmore:

import Vue from "vue";
export default {}.install = (Vue, options = {}) => {
  Vue.directive("loadmore", {
    inserted(el, binding) {
      // 获取element-ui定义好的scroll盒子
      const SELECTDOWN_DOM = el.querySelector(
        ".el-select-dropdown .el-select-dropdown__wrap"
      );
      SELECTDOWN_DOM.addEventListener("scroll", function () {
        const CONDITION =
          this.scrollHeight - this.scrollTop <= this.clientHeight + 2;
        if (CONDITION) {
          binding.value();
        }
      });
    },
  });
};

代码说明:

document.querySelector:querySelector() 方法仅仅返回匹配指定选择器的第一个元素。
Element.scrollHeight:在不使用滚动条的情况下为了适应视口中所用内容所需的最小高度(只读)
Element.scrollTop:获取或设置一个元素的内容垂直滚动的像素数。
Element.clientHeight:读取元素的可见高度(只读)。
元素滚动到底,下面等式返回true,没有则返回false。
警告: 在使用显示比例缩放的系统上,scrollTop可能会提供一个小数。

2.在 mian.js 引入封装好的自定义指令

import loadMore from './plugins/select'
Vue.use(loadMore)

3、创建一个组件LazySelect.vue

<template>
  <div>
    <el-select
      v-model="selectData"
      v-loadmore="handleScroll"
      filterable
      remote
      clearable
      :remote-method="remoteMethod"
      @clear="clearSelect"
    >
      <el-option
        v-for="item in meetList"
        :key="item.id"
        :label="item.name"
        :value="item.id"
      >
      </el-option>
    </el-select>
  </div>
</template>

<script>
export default {
  name: "LazySelect",
  props: {
    // 外部传入的获取数据的方法
    fetchDataMethod: {
      type: Function,
      required: true,
    },

    getSelectDataMethod: {
      type: Function,
      required: true,
    },
  },
  data() {
    return {
      meetList: [], //案件数据
      total: 0, //案件所有总数(接口返回)
      dqmeetTotal: 0, //当前案件总数(每次存储的长度)
      meetTotal: 0, //案件总数
      selectfy: {
        page: 0, //当前页码
        size: 20, //每页显示条数
      },
      selectData: null, //选中的案件数据
    };
  },
  watch: {
    selectData: {
      handler(val) {
        let valData = val && val != null ? val.toString() : null;
        this.getSelectDataMethod(valData);
      },
      deep: true,
    },
  },
  created() {
    this.getMeetnewlist(); //获取
  },
  methods: {
    handleScroll() {
      console.log(this.dqmeetTotal, this.meetTotal);
      if (this.meetList.length < this.meetTotal) {
        this.getMeetnewlist(); //获取
      }
    },
    // 获取案件
    getMeetnewlist() {
      this.selectfy.page = this.selectfy.page + 1;
      this.fetchDataMethod("", this.selectfy.page, this.selectfy.size).then(
        (res) => {
          this.meetList = this.meetList.concat(res.rows); //案件信息
          this.dqmeetTotal = this.meetList.length; //当前案件总数
          this.meetTotal = res.total; //案件所有总数(接口返回)
        }
      );
    },
    // 关联案件下拉菜单远程搜索
    remoteMethod(val) {
      this.fetchDataMethod(val, 1, this.selectfy.size).then((res) => {
        this.meetList = res.rows ? res.rows : []; //案件信息
        this.dqmeetTotal = this.meetList.length; //当前案件总数
        this.meetTotal = res.total; //案件所有总数(接口返回)
      });
    },
    clearSelect() {
      this.selectfy.page = 0;
      this.meetList = [];
      this.getMeetnewlist(); //获取
    },
  },
};
</script>

<style scoped>
/* 自定义样式(如果需要) */
</style>

4、在页面中使用组件:

html部分:

<el-form-item
          label="会议名称:"
          prop="meetingId"
          v-if="modalType == '1'"
        >
          <LazySelect
            :fetchDataMethod="fetchDataFromServer"
            :getSelectDataMethod="getSelectData"
          />
        </el-form-item>

js部分:

components: {
    LazySelect: () => import("@/components/managementMeeting/LazySelect.vue"),
  },

methods(){
 //会议名称查询
    fetchDataFromServer(query, page, pageSize) {
      console.log("query, page, pageSize", query, page, pageSize);
      return new Promise((resolve, reject) => {
        let param = {
          name: query,
          pageNum: page,
          pageSize: pageSize,
        };

        // 假设 meetingRecordSelect 是一个返回 Promise 的函数
        meetingRecordSelect(param)
          .then((response) => {
            if (response.code === 200) {
              if (response) {
                resolve(response); // 返回获取到的数据
              } else {
                resolve([]); // 如果没有数据,返回空数组
              }
            } else {
              reject(new Error("查询失败,返回错误代码:" + response.code)); // 如果接口返回的 code 不为 200,拒绝 Promise
            }
          })
          .catch((error) => {
            reject(error); // 如果请求发生错误,拒绝 Promise
          });
      });
    },
//选中的数据
 getSelectData(data) {
      this.form.meetingId = data;
    },
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值