封装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 的兄弟组件中传值

猜你喜欢

转载自blog.csdn.net/weixin_46054723/article/details/130553409