IntersectionObserver 实现滚动加载
- 如果你不喜欢繁琐onscroll,那么试一试IntersectionObserver吧
- 下面有完整代码,逻辑写在注释里了
话不多说上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
.box {
display: flex;
flex: 1;
flex-direction: column;
width: 400px;
height: 100%;
margin: 0 auto;
border: 1px solid blue;
min-height: 100px;
max-height: 600px;
margin-top: 30px;
overflow: auto;
}
.list {
flex: 1;
}
.top {
width: 100%;
height: 50px;
}
.bottom {
width: 100%;
min-height: 50px;
background:
text-align: center;
line-height: 50px;
}
.item-list {
width: 90%;
height: 100px;
border: 1px solid red;
margin: 10px auto;
}
</style>
</head>
<body>
<div id="content" class="box">
<ul id="list" class="list">
// 数据加载位置
</ul>
// 加载触发守卫
<div id="bottom" class="bottom">...LoadingMore....</div>
</div>
</body>
<script src="./index.js"></script>
</html>
let list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
class LoadMore {
constructor(options) {
this.observer = null;
this.rootNode = document.getElementById(options.root); // 父级容器
this.obsNode = document.getElementById(options.obs); // 守卫节点
this.loadMoreFn = options.loadMoreFn // 加载回调
this.pageNum = 0; // 记录页数
this.total = -1; // 总页数 -1 // 尚未获取
this.init() // 初始化
}
// 交叉触发回调
callback = (entries) => {
console.log(111)
// 防止插入瞬间再次触发离开交叉事件
if (entries[0].intersectionRatio === 0) return;
this.pageNum += 1
this.loadMoreFn(this.pageNum)
}
// 关闭交叉监听
canclobserve() {
console.log('完毕')
this.observer.unobserve(this.obsNode)
}
// 设置首位节点交叉监听
hanldeObserve() {
this.observer.observe(this.obsNode)
}
// 初始化
init() {
// 创建 IntersectionObserver 实例子
this.observer = new IntersectionObserver(this.callback, {
root: this.rootNode || null, // 交叉窗口、根元素
rootMargin: '0px', // 交叉窗口边界扩展或者伸缩
threshold: 0.8 // 交叉占比(0~1),达到该比例才触发回调
});
this.hanldeObserve()
}
}
let loadEx = new LoadMore({
root: 'content',
obs: 'bottom',
loadMoreFn: (pageNum) => {
// 最好一页关闭监听
if (pageNum * 10 > list.length) {
loadEx.canclobserve()
}
// 插入dom
let curPage = list.slice((pageNum - 1) * 10, pageNum * 10)
// 创建文档碎片
let frm = document.createDocumentFragment();
for (let i = 0; i < curPage.length; i++) {
let li = document.createElement('li')
li.innerHTML = curPage[i];
li.className = "item-list"
frm.appendChild(li)
}
document.getElementById('list').appendChild(frm);
frm = null;
}
})