想必做前端的小伙伴在 H5
端开发都遇到过 「下拉加载更多」的需求,由于时间关系,以及兼容性考虑上,大家一定优先考虑的是开源的组件库,诸如 antd-mobile
等。
本期主要讲述下几个的实现思路,如有勘误,欢迎在「阅读原文」-> 「评论区」批评指正。
方案
方案一
- 1. 监听滚动区域的
touchMove
事件; - 2. 设置提前触发加载更多的阈值空间,比如:滚动条距离底部还有多少像素时触发;
- •
scrollHeight
- •
scrollTop
- •
clientHeight
- • 最终公式
scrollHeight - scrollTop - clientHeight <= limitHeight
,其中limitHeight
为阈值
- •
- 3. 节流监听,优化滚动性能,防抖控制请求函数,防止多次触发;
图片来源于:https://javascript.info/size-and-scroll
方案二
- 1. 借助
IntersectionObserver
监听哨兵(这个哨兵可以作为滚动区域内的最后一个兜底元素或者隐藏的元素,或者边距元素); - 2. 到达元素即加载更多,全部加载完成可取消监听;
实现
由于 方案一
的性能不太好,所以这里我仅介绍方案二,相对比较完美,另外对于低版本也可以引入 polyfill
做兼容。
代码实现
代码语言:javascript复制
const watchSentry =async () => {
// 低版本浏览器兼容,引入 polyfill
if(!window.IntersectionObserver) {
await import('intersection-observer');
}
const el = document.getElementById('Sentry')
if (el) {
// 初始化观察者
const intersectionObserver = new IntersectionObserver(function (entries) {
// 如果没有更多元素了,这里就可以释放了
// some code
// intersectionObserver.unobserve();
// 判定元素交叉比例
if (entries[0].intersectionRatio <= 0) return
setLoading(true);
Promise.resolve()
.then(() => {
setTimeout(() => {
setData(pre => ([
...pre,
...getData()
]));
setLoading(false);
}, 800);
});
});
// 监听哨兵元素
intersectionObserver.observe(el);
}
}
其余的代码如有需要可在「阅读原文」-> 「留言区」留言奥~
小结
文中我仅仅罗列了一个核心函数 watchSentry
,里面做了三件事:
- • 浏览器兼容
- • 监听哨兵(容错)
- • 适当时机释放
优化的空间
当然,还有很多优化的空间:
- • 借助
react-window
或者react-virtualized
,或者其它虚拟列表实现技术,进行大数据调优; - •
loading
态的动画; - •
IOS
的滚动兼容,可以考虑iScroll
或者better-scroll
进行调优; - • ......