Hibop.github.io
Hibop.github.io copied to clipboard
关于vue滚动懒加载实现方案
先看问题
一个下拉列表拉取上千条数据; 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则阻止该事件。