el-select封装懒加载分页

el-select懒加载滚动触底懒加载

直接复制封装组件使用

代码:

<template>

  <el-select

    :disabled="disabled"

    v-model="selectValue"

    v-loadmore="loadMore"

    @focus="focus"

    @clear="clear"

    filterable

    :placeholder="placeholder"

    remote

    :filter-method="handleSearch"

    :loading="loading"

    @change="selectChange"

    clearable

    v-bind="$attrs"

    v-on="$listeners"

  >

    <el-option

      v-for="option in data"

      :label="option[dictLabel]"

      :value="option[dictValue]"

      :key="option.value"

    >

      <span style="float: left">{{ option[dictLabel] }}</span>

      <span

        v-if="dictRight"

        style="float: right; color: #8492a6; font-size: 13px"

        >{{ option[dictRight] }}</span

      >

    </el-option>

    <!-- 此处加载中的value可以随便设置,只要不与其他数据重复即可 -->

    <el-option

      v-if="!hasMore"

      disabled

      label="加载完毕..."

      value="-1"

    ></el-option>

  </el-select>

</template>

<script>

export default {

  props: {

    disabled: {

      type: Boolean,

      default: false,

    },

    value: {

      type: Number,

      default: null,

    },

    placeholder: {

      type: String,

      default: "请选择",

    },

    dictRight: {

      type: String,

      default: null,

    },

    dictLabel: {

      type: String,

      default: "label",

    },

    dictValue: {

      type: String,

      default: "value",

    },

    // 查询属性名

    selectArr: {

      type: String,

      default: "name",

    },

    // 响应数据的属性名

    responseValue: {

      type: String,

      default: "rows",

    },

    // 调用页数的接口

    request: {

      type: Function,

      default: () => {},

    },

    // 传入的页距

    pageSize: {

      type: [Number, String],

      default: 10,

    },

  },

  directives: {

    // 这里实现一个组件内部的自定义指令

    loadmore: {

      // 指令的定义

      bind(el, binding) {

        const SELECTWRAP = el.querySelector(

          ".el-select-dropdown .el-select-dropdown__wrap"

        );

        if (!SELECTWRAP) {

          throw new Error('获取不到"el-select-dropdown__wrap"节点');

        }

        SELECTWRAP.addEventListener("scroll", () => {

          // scrollTop  这里可能因为浏览器缩放存在小数点的情况,导致了滚动到底部时

          // scrollHeight 减去滚动到底部时的scrollTop ,依然大于clientHeight 导致无法请求更多数据

          // 这里将scrollTop向上取整 保证滚到底部时,触发调用

          const CONDITION =

            SELECTWRAP.scrollHeight - Math.ceil(SELECTWRAP.scrollTop) <=

            SELECTWRAP.clientHeight;

          // el.scrollTop !== 0 当输入时,如果搜索结果很少,以至于没看到滚动条,那么此时的CONDITION计算结果是true,会执行bind.value(),此时不应该执行,否则搜索结果不匹配

          if (CONDITION && SELECTWRAP.scrollTop !== 0) {

            binding.value();

          }

        });

      },

    },

  },

  data() {

    return {

      pageNum: 1,

      data: [],

      keyword: "", // 存储关键字用

      loading: false,

      hasMore: true,

      selectValue: null,

    };

  },

  watch: {

    value: {

      immediate: true, // 立即执行

      handler(newVal, oldVal) {

        this.selectValue = null;

        if (newVal) {

          this.selectValue = newVal;

          this.getList({ id: newVal });

        }

      },

    },

  },

  methods: {

    selectChange(value) {

      let selectData = this.data.find((item) => item[this.dictValue] == value);

      this.$emit("selectChange", selectData);

    },

    // 请求下一页的数据

    loadMore() {

      if (this.hasMore) {

        this.pageNum++;

        let req = {

          pageNum: this.pageNum,

          pageSize: this.pageSize,

        };

        req[this.selectArr] = this.keyword;

        this.getList(req);

      }

    },

    // 选中下拉框没有数据时,自动请求第一页的数据

    focus() {

      this.data = [];

      this.keyword = "";

      if (!this.data.length) {

        this.pageNum = 1;

        this.getList({ pageNum: this.pageNum, pageSize: this.pageSize });

      }

    },

    // 发送请求搜索

    handleSearch(keyword) {

      this.data = [];

      this.keyword = keyword;

      let req = {

        pageNum: 1,

        pageSize: this.pageSize,

      };

      req[this.selectArr] = keyword;

      this.getList(req);

    },

    getList(req) {

      this.loading = true;

      this.request(req).then((res) => {

        let resData = res[this.responseValue];

        this.data = [...this.data, ...resData];

        this.hasMore = this.data.length < res.total;

        this.loading = false;

      });

    },

    // 删除选中时,如果请求了关键字,则清除关键字再请求第一页的数据

    clear() {

      this.data = [];

      if (this.keyword) {

        this.keyword = "";

        this.pageNum = 1;

        this.getList({ pageNum: this.pageNum, pageSize: this.pageSize });

      }

    },

  },

};

</script>

效果图:

确保可以使用id查询,否则无法回显



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值