【前端】Ant Design of Vue a-select下拉框因为数据量太大造成卡顿的问题【滑动加载+模糊查询】

        实际需求:在项目中一个下拉框中需要展示10000条数据,这10000条数据去后端查询虽然比较快,但是将查询结果返回给前端需要进行渲染,前端就会造成卡顿的现象,这时候就可以使用滑动加载只渲染总数据前100条数据以保证不卡顿。

        然后当需要搜索的时候对从后台拿到的数据进行过滤,也只取前100条,然后通过select下拉框popupScroll事件,下拉列表滚动时的回调,每次回调时都添加一部分数据来解决下拉框的卡顿问题。

        虽然解决了卡顿问题,但是非常的不方便查询数据,这时候就需要对下拉框实现一个模糊查询的功能,从而解决了滑动加载所带来的不便,满足需求。

官方文档

https://www.antdv.com/components/select-cn/#API

效果图

 模板

代码部分:

html:【滑动加载主要跟@popupScroll="handlePopupScroll"有关,模糊查询与showSearch和@search有关】

        @search 可以获取到当前输入的Value值

<a-select
    allowClear
    mode="multiple"
    placeholder="供应商"
    style="width: 100%"
    :value="sourceOwnerSystems"
    showSearch
    @change="onTreeSelect"
    @popupScroll="handlePopupScroll"
    @search="handleSearch"
  >
    <a-select-option v-for="frontSelect in frontDataZ.filter(item=>item.sourceOwnerSystems)" :key="frontSelect.sourceOwnerSystems"> //过滤一下数据是否为空
      {{ frontSelect.sourceOwnerSystems }}
    </a-select-option>
</a-select>

js:

(1).data中定义变量与数组

data(){
  return {
    dataZ: [],//总数据(不会改变),从后端查询的所有数据。
    frontDataZ: [], //存放前100的数据
    sourceOwnerSystems: [], //集合(过滤后的)
    valueData: '',
    treePageSize: 100,
    scrollPage: 1
  }
}

(2).methods:

//通过接口获取数据
showTabelCiList () {
  // 发送请求
  listSimpleInfos({sourceOwnerSystems: this.sourceOwnerSystems}).then(res => {
    if (res && res.data) {
      this.dataZ = res.data  // 获取所有的数据赋值给dataZ 
      this.frontDataZ = res.data.slice(0, 100) // 只渲染100条数据
    }
  }).catch(e => {
    this.$message.error('查询维护信息失败:' + e)
  })
},

// 搜索的时候执行的方法,val就是输入的时候的内容,可以去后端进行查询数据最后赋值给dataZ或者frontDataZ
handleSearch (val) {
  this.valueData = val
  if (!val) {
    this.showTabelCiList()
  } else {
    this.frontDataZ = []
    this.scrollPage = 1
    this.dataZ.forEach(item => {
      if (item.instanceId.indexOf(val) >= 0) {
        this.frontDataZ.push(item)
      }
    })
   
    this.allDataZ = this.frontDataZ 
    this.frontDataZ = this.frontDataZ.slice(0, 100) // 只渲染100条数据
  }
},

//下拉框下滑事件
handlePopupScroll (e) {
  const { target } = e
  const scrollHeight = target.scrollHeight - target.scrollTop
  const clientHeight = target.clientHeight
  // 下拉框不下拉的时候
  if (scrollHeight === 0 && clientHeight === 0) {
    this.scrollPage = 1
    console.log(this.scrollPage)
  } else {
    // 当下拉框滚动条到达底部的时候
    if (scrollHeight < clientHeight + 5) {
      this.scrollPage = this.scrollPage + 1
      const scrollPage = this.scrollPage// 获取当前页
      const treePageSize = this.treePageSize * (scrollPage || 1)// 新增数据量
      const newData = [] // 存储新增数据
      let max = '' // max 为能展示的数据的最大条数
      if (this.dataZ.length > treePageSize) {
        // 如果总数据的条数大于需要展示的数据
        max = treePageSize
      } else {
        // 否则
        max = this.dataZ.length
      }
      // 判断是否有搜索
      if (this.valueData) {
        this.allDataZ.forEach((item, index) => {
          if (index < max) { // 当data数组的下标小于max时
            newData.push(item)
          }
        })
      } else {
        this.dataZ.forEach((item, index) => {
          if (index < max) { // 当data数组的下标小于max时
            newData.push(item)
          }
        })
      }

      this.frontDataZ = newData // 将新增的数据赋值到要显示的数组中
    }
  }
}

实际项目代码改造

代码部分:

html:

<!--下拉框  -->
            <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="供应商" data-step="1" data-title="供应商">
              <!--  @popupScroll="handlePopupScroll"滑动加载  -->
              <a-select placeholder="选择供应商"
                        v-decorator="[ 'organId',validatorRules.organId]"
                        :dropdownMatchSelectWidth="false"
                        showSearch
                        optionFilterProp="children"
                        @popupScroll="handlePopupScroll"
                        allowClear
                        @search="supValue"
>     
<!--上面就多加了一个@popupScroll="handlePopupScroll"滑动加载和@search="supValue"获取输入框的值-->         
                <!--这个是下拉框 frontDataZSupplier 供应商-->
<!--    原本的代码 <a-select-option v-for="(item,index) in supList" :key="index" :value="item.id">
                  {{ item.supplier }}
                  </a-select-option>-->
                <a-select-option v-for="item in frontDataZSupplier.filter(item=>item.supplier)" :key="item.supplier" :value="item.id">
                  {{ item.supplier }}
                </a-select-option>
              </a-select>
            </a-form-item>

js:

(1).data中定义变量与数组

 data() {
    return {
      /**
       * 滑动加载
       * */
      supList: [], //从后端查询的所有数据(不会改变)
      frontDataZSupplier:[], // 供应商 100条数据的集合
      sourceOwnerSystems: [], // 供应商名称的集合(过滤)
      treePageSize: 100,
      scrollPage: 1,
    }
}

(2).methods:

     /**
     * 点击编辑页面,页面初始化的时候就会发送请求去后端进行查询供应商
     * */
    initSupplier() {
      let that = this;
      findBySelectSup({}).then((res) => {
        if (res) {
          // 将查询到的数据直接赋值给supList集合
          that.supList = res;
          // add 滑动加载数据
          that.frontDataZSupplier = res.slice(0, 100) // 展示100条数据,如果100条还是卡顿,可以改小
        }
      });
    },

Vue页面:下面方法我只将以前的dataZ(总数据)改成我自己的supList,frontDataZ改成了frontDataZSupplier。

//下拉框下滑事件
handlePopupScroll (e) {
  const { target } = e
  const scrollHeight = target.scrollHeight - target.scrollTop
  const clientHeight = target.clientHeight
  // 下拉框不下拉的时候
  if (scrollHeight === 0 && clientHeight === 0) {
    this.scrollPage = 1
    console.log(this.scrollPage)
  } else {
    // 当下拉框滚动条到达底部的时候
    if (scrollHeight < clientHeight + 5) {
      this.scrollPage = this.scrollPage + 1
      const scrollPage = this.scrollPage// 获取当前页
      const treePageSize = this.treePageSize * (scrollPage || 1)// 新增数据量
      const newData = [] // 存储新增数据
      let max = '' // max 为能展示的数据的最大条数
      if (this.supList.length > treePageSize) {
        // 如果总数据的条数大于需要展示的数据
        max = treePageSize
      } else {
        // 否则
        max = this.supList.length
      }
      // 判断是否有搜索
      if (this.valueData) {
        this.allDataZ.forEach((item, index) => {
          if (index < max) { // 当data数组的下标小于max时
            newData.push(item)
          }
        })
      } else {
        this.supList.forEach((item, index) => {
          if (index < max) { // 当data数组的下标小于max时
            newData.push(item)
          }
        })
      }

      this.frontDataZSupplier= newData // 将新增的数据赋值到要显示的数组中
    }
  }
}

 Vue页面:将输入框中的内容获取到去后端进行模糊查询,然后将查询的数据赋值给下拉框

/**
     * 获取到输入框中的内容
     * */
    supValue(value) {
      if (value) {
        // BillModalMixin.js中的方法去后端进行查询数据
        this.getSupplier(value);
      }
    },

js:

methods:{
/**
     * 模糊查询去后端查询供应商集合数据
     * */
    getSupplier(value){
     let parms ={
        supplierName:value
      }
      getAction('/supplier/getSupplier',parms).then((res) => {
        if (true) {
          this.supList=res // 所有数据
          this.frontDataZSupplier = res.slice(0,30) // 滑动加载的数据(30条)
        }
      })
    },
}

  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mxin5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值