封装el-select数据量过大懒加载组件

之前出过一篇《解决el-select数据量过大导致页面卡顿》的博客。最近在开发过程中发现需要用到的地方很多,并且发现change事件与blur事件在一起使用会出bug,于是开发了一个公共组件。

1、封装组件selectLoadmore.vue

<template>
  <div>
    <el-select clearable filterable v-model="selected"
               :filter-method="(e)=>searchGoodsList(e)"
               ref="mySelect"
               v-el-select-loadmore:rangeNumber="loadMore(rangeNumber)"
               @change="handleChange" @blur.capture="handleBlur" :placeholder="text">
      <el-option
        v-for="(item,index) in dataList.slice(0, rangeNumber)"
        :key="index"
        style="width: 200px"
        :label="item"
        :value="item">
      </el-option>
    </el-select>
  </div>
</template>

<script>
  export default {
    name: "selectLoadmore",
    directives: {
      "el-select-loadmore": function(el,binding) {
        let self = this
        // 获取element-ui定义好的scroll盒子
        const SELECTWRAP_DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
        if(SELECTWRAP_DOM){
        	 SELECTWRAP_DOM.addEventListener('scroll', function () {
	          /**
	           * scrollHeight 获取元素内容高度(只读)
	           * scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
	           * clientHeight 读取元素的可见高度(只读)
	           * 如果元素滚动到底, 下面等式返回true, 没有则返回false:
	           * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
	           */
	          const condition = this.scrollHeight - Math.ceil(this.scrollTop) <= this.clientHeight;
	          if (condition) binding.value()
        });
        }
       
      }
    },
    props: {
      value: String,
      text: String,
      name: String,
      dataArr: Array,
      filterList: Array,
    },
    data() {
      return {
        selected:'',
        dataList:[],
        rangeNumber:10,
        status:false,
      }
    },
    watch:{
      dataArr(val) {
        this.dataList=val
      },
      value(val){
        this.selected=val
      },
    },
    mounted() {
      // const mySelect = this.$refs.mySelect;
      // mySelect.$on('customChangeAndBlur', () => {
      //   this.$nextTick(()=>{
      //     mySelect.$emit('change');
      //     mySelect.$el.querySelector('.el-input__inner').dispatchEvent(new Event('blur'));
      //   })
      // });
      // mySelect.$el.addEventListener('blur', () => {
      //   this.$nextTick(()=>{
      //     this.$bus.$emit('blurEvent', mySelect);
      //   })
      // });
      this.$refs.mySelect.$el.querySelector('.el-input__inner').addEventListener('blur', this.handleBlur);
    },
    beforeDestroy() {
      this.$refs.mySelect.$el.querySelector('.el-input__inner').removeEventListener('blur', this.handleBlur);
    },
    methods:{
      handleBlur(event) {
        if(this.filterList.length!==1){
          this.status=false
        }else {
          this.status=true
        }
        if(!this.status){
          // this.$refs.mySelect.$emit('change');
          this.$bus.$emit('blurEvent', this.selected,this.name);
        }
      },
      handleChange(){
        this.status=true
        this.$bus.$emit('changeEvent', this.selected,this.name);
      },
      searchGoodsList(e){
        this.selected=e//注意:这里一定要给value赋值
        if (e) { //val存在
          this.dataList = this.filterList.filter((item) => {
            if (!!~item.indexOf(e) || !!~item.toUpperCase().indexOf(e.toUpperCase())) {
              return true
            }
          })
        } else { //val为空时,还原数组
          this.dataList = this.filterList;
        }
      },
      loadMore(n){
        //n是默认初始展示的条数会在渲染的时候就可以获取,具体可以打log查看
        //if(n < 8) this.rangeNumber = 10 //elementui下拉超过7条才会出滚动条,如果初始不出滚动条无法触发loadMore方法
        return () => this.rangeNumber += 5 //每次滚动到底部可以新增条数  可自定义
      },
    }
  }
</script>

<style scoped>

</style>

2、页面使用

<template>
  <my-select text="请输入名称"
       name="name"
       :dataArr="list"
       :filterList="list"
       :value="form.name">
   </my-select>
</template>
<script>
  import SelectLoadmore from '@/components/selectLoadmore'
  export default {
    name: "index",
    components: {
      'my-select':SelectLoadmore,
    },
    data() {
      return {
        list:['小红','张三','小明','李四','王五'],
        form:{
          name:''
        },
      }
    },
    mounted() {
      this.$bus.$off('changeEvent')
      this.$bus.$off('blurEvent')
      this.$bus.$on('changeEvent', (selected, name) => {
        this.form[name]=selected
        this.changeVal()
      });
      this.$bus.$on('blurEvent', (selected, name) => {
        if(selected){
          this.form[name]=selected
          this.changeVal()
        }
      });
    },
    methods:{
      changeVal(){
        let _this=this
        setTimeout(function(){
          _this.pageIndex = 1
          _this.getDataList()
          // 时间间隔
        },500);
      },
      getDataList(){
      //此方法中做查询操作
      console.log(this.form.name)
      },
    }
}
</script>

补充:

文中用到了this.$bus,可以看下我上篇博文:
Vue组件之间传值,使用全局 bus 在 Vue 的兄弟组件中传值

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
封装el-select可以通过在HTML模板中使用el-select组件,并根据需要添加相应的样式和逻辑操作。首先,你可以在HTML模板中使用el-select组件,并设置相应的属性和事件。例如,你可以设置v-model属性来绑定选择的值,设置placeholder属性来显示默认提示文字,设置class属性来添加自定义样式,设置filterable属性来启用搜索功能,设置allow-create属性来允许创建新选项,设置clearable属性来显示清空按钮,并通过@change事件来监听选项变更并执行相应的逻辑操作。\[2\] 接下来,你可以在CSS样式中覆盖el-select组件的原本样式,以满足你的需求。你可以使用/deep/选择器来覆盖el-select组件的样式,并根据需要设置不同的样式属性,如padding、margin、color、font-size等。你还可以使用:hover伪类来设置鼠标悬停时的样式效果。\[1\] 此外,你还可以在JavaScript中定义hotOptions数组来存储el-select的选项数据。你可以根据需要添加不同的选项组,并在每个选项组中定义相应的选项。在选项变更时,你可以通过调用queryDataPage方法来执行相应的逻辑操作。\[3\] 综上所述,你可以根据需要在HTML模板中使用el-select组件,并根据需要设置样式和逻辑操作,同时在CSS样式和JavaScript中进行相应的定制和处理。 #### 引用[.reference_title] - *1* *2* *3* [组件封装封装 el-select 组件,实现关键词(经常搜索、热点搜索)提示 >](https://blog.csdn.net/MrWen2395772383/article/details/124951077)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值