Hibop.github.io icon indicating copy to clipboard operation
Hibop.github.io copied to clipboard

关于vue滚动懒加载实现方案

Open Hibop opened this issue 7 years ago • 0 comments

先看问题

一个下拉列表拉取上千条数据; dashboard图表卡片无分页下拉; ==> 页面直接卡死,或者长时间白屏。非常影响体验

方法

  • 监听滚动
  • 向下滚动时往后加载数据
  • 向上滚动时往前加载数据
  • 数据有进有出
import Vue from 'vue';
  const scrollDirective = Vue.directive('scroll', {
    bind (el, binding) {
      // 获取滚动页面DOM
      let scrollPosition = 0;
      el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
        .addEventListener('scroll', function() {
          // 当前的滚动位置 减去  上一次的滚动位置
          // 如果为true则代表向上滚动,false代表向下滚动
          let flagPosition = this.scrollTop - scrollPosition > 0;
          // 记录当前的滚动位置
          scrollPosition = this.scrollTop;
          binding.value(flagPosition); // 将滚动行为告诉组件
          console.log(flagPosition ? '滚动方向:下' : '滚动方向:上');
        });
    }
  })


  Vue.use(scrollDirective);

  <el-select class="remoteSelect" v-scroll="handleScroll" v-model="value">
    <el-option :value="item.id" v-for="item in list" :key="item.id">{{item.name}}</el-option>
  </el-select>

  handleScroll(flagPosition) {
  // 收到滚动行为
    if(flagPosition) {
      this.list.push(...this.ajaxData(++this.pageIndex));
    }
  }

滚动加载已经实现。只是加载太频繁了,如果快速滚动则会同时发出多个请求后台数据,在密集一些游览器中ajax就要开发并发排队了,可见并不理想。那如何控制呢?那换种方式触发handleScroll事件,在滚动位置距离滚动页面底部一定高度时在触发,例如距页面底部只有100px时触发handleScroll事件

距离底部Npx再请求

       // 记录当前的滚动位置
        scrollPosition = this.scrollTop
        const LIMIT_BOTTOM = 100
        // 记录滚动位置距离底部的位置
        let scrollBottom = this.scrollHeight - (this.scrollTop + this.clientHeight) < LIMIT_BOTTOM
        // 如果已达到指定位置则触发
        if (scrollBottom) {
          // 将滚动行为告诉组件
          binding.value(flagToDirection)
        }

注意事项 会存在一个bug,即ajax是异步的,如果这个ajax请求花了1s才返回数据,而此时还在继续往下滚,那就会触发多个请求事件。如何避免这种情况呢? 答案是增加一个标志位,在请求前将该标志位设置为false,请求结束后设置为true。每次请求时先判断该标志位。如果为false则阻止该事件。

Hibop avatar Nov 09 '18 12:11 Hibop