技术栈
- Vue.js
- ElementUi
无限滚动优点
解决dom一次性渲染开销大, 导致浏览器卡顿, 或者内存不足崩溃
无限滚动缺点:
理论上无限滚动数据量达到w级也会逐步开始卡顿, 暂时还没尝试过
针对vue框架做了directive(自定义指令 — Vue.js)的形式开发, 代码如下
// src/directive/lazyLoading.js
function debounce(fn, delay) {
// 防抖
var timeout = null; // 创建一个标记用来存放定时器的返回值
return (e) => {
clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
// 然后又创建一个新的 setTimeout, 这样就能保证interval 间隔内如果时间持续触发,就不会执行 fn 函数
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
export default {
install(Vue) {
Vue.directive("lazyLoading", {
bind(el, binding) {
const { value } = binding;
let elementClass = null;
let lazyFun = null;
if (typeof value == "object") {
const { elementClass: _elementClass, lazyFun: _lazyFun } = value; // elementClass 滚动盒子的class, lazyFun 调用的函数
elementClass = _elementClass;
lazyFun = _lazyFun;
} else if (typeof value == "function") {
lazyFun = value;
} else {
console.err("传参错误");
return;
}
// 获取element-ui定义好的scroll盒子
const SELECTWRAP_DOM = el.querySelector("." + elementClass);
SELECTWRAP_DOM.addEventListener("scroll", function () {
let { clientHeight, scrollTop, scrollHeight } = this;
// 当用户的滚动距离大于等于滚动条的总高度, 就执行lazyFun方法
const CONDITION = Math.ceil(clientHeight + scrollTop) >= scrollHeight;
if (CONDITION) {
debounce(lazyFun(), 300);
}
});
},
});
},
};
// src/main.js 在入口文件引入, vue实例生成前调用
import lazyLoading from "@/directive/lazyLoading";
Vue.use(lazyLoading);
new Vue({
el: "#app",
...
});
// 页面使用
<el-scrollbar
v-lazy-loading="{
lazyFun: lazyFun,
elementClass: 'el-scrollbar__wrap',
}"
>
...
</el-scrollbar>
<script>
export default {
data() {
return {
renderNum: 0, //渲染次数
renderList: [], //渲染的数据
};
},
methods: {
// 初始化懒加载数据 从0开始
initLazyFun() {
let count = 5;
this.renderList = this.upList.slice(0, count);
this.renderNum += count;
},
// 更新当前懒加载数据 仅更新renderNum数量, 不继续+count
updateLazyFun() {
this.renderList = this.upList.slice(0, this.renderNum);
},
// 懒加载数据
lazyFun() {
let count = 5;
this.renderList = this.upList.slice(0, this.renderNum + count);
this.renderNum += count;
},
};
</script>
自定义指令拓展
指令钩子函数会被传入以下参数:
-
el
:指令所绑定的元素,可以用来直接操作 DOM。 binding
:一个对象,包含以下 property:
-
name
:指令名,不包括v-
前缀。 -
value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为2
。 -
oldValue
:指令绑定的前一个值,仅在update
和componentUpdated
钩子中可用。无论值是否改变都可用。 -
expression
:字符串形式的指令表达式。例如v-my-directive="1 + 1"
中,表达式为"1 + 1"
。 -
arg
:传给指令的参数,可选。例如v-my-directive:foo
中,参数为"foo"
。 -
modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为{ foo: true, bar: true }
。
-
vnode
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。 -
oldVnode
:上一个虚拟节点,仅在update
和componentUpdated
钩子中可用。
文章参考
vue2.0 自定义指令 ++ element-ui 自定义el-select的下拉懒加载指令