目录
1.通过计算scroll到元素底部距离实现
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>Infinity scroll</title>
</head>
<style>
.outer{
height: 200px;width: 200px;
background: #aaa;
overflow: auto;
}
.outer .inner {
height: 50px;
color: #fff;
border:1px solid black;
line-height: 50px;
font-size: 20px;
font-weight: bold;
text-align: center;
}
.outer .loading {
text-align:center;
font-size: 12px;
color: #eee;
text-shadow: 0 0 2px rgba(0,0,0,0.5);
}
</style>
<body>
<div class="outer" id="outer">
</div>
</body>
<script>
let outer = document.querySelector('#outer');
let loading = document.createElement('div');
loading.classList.add('loading');
loading.textContent = 'loading';
let requestFlag = false; // whether get http response
// add scroll event listener
outer.addEventListener('scroll', (e) => {
// 计算滚动条距离底部的距离
let scrollBottom = e.target.scrollHeight - e.target.offsetHeight - e.target.scrollTop;
if(scrollBottom < 20 && !requestFlag){
request();
}
})
window.onload = function() {
rendering(5); // first page
}
function request(){
let childrenLength = Array.from(outer.children).filter(it => it.className === 'inner').length;
requestFlag = true;
setTimeout(() => {// simulate request
requestFlag = false;
if(childrenLength >= 30){ // max data size
requestFlag = true; // all data return ,never set requestFlag false again
loading.textContent = 'all return';
return
}
outer.removeChild(loading); // remove loading element
rendering(5);
}, 1000);// delay 1s to simulate request
}
/**
* append child
*/
function rendering(size){
for (let i = 0; i < size; i++) {
let div = document.createElement('div');
div.classList.add('inner');
div.textContent = i;
div.style.backgroundColor = `rgb(${parseInt(Math.random()*255)},${parseInt(Math.random()*255)},${parseInt(Math.random()*255)})`;
outer.appendChild(div);
}
outer.append(loading);
}
</script>
</html>
原理是通过监听scroll距离底部的距离来判断是否开始加载
2.使用IntersectionObserver实现
IntersectionObserver MDN
当被监听的元素可见性变化时(进入或离开其父元素时)触发回调。
这里通过监听loading元素是否进入可视区来触发加载下一页的操作
代码
<!DOCTYPE html>
<html lang="zh_CN">
<head>
<meta charset="UTF-8">
<title>Infinite scroll</title>
</head>
<style>
.outer{
height: 200px;width: 200px;
background: #aaa;
overflow: auto;
}
.outer .inner {
height: 50px;
color: #fff;
border:1px solid black;
line-height: 50px;
font-size: 20px;
font-weight: bold;
text-align: center;
}
.outer .loading {
text-align:center;
font-size: 12px;
color: #eee;
text-shadow: 0 0 2px rgba(0,0,0,0.5);
}
</style>
<body>
<div class="outer" id="outer">
</div>
</body>
<script>
let outer = document.querySelector('#outer');
let loading = document.createElement('div');
loading.classList.add('loading');
loading.textContent = 'loading';
let requestFlag = false; // whether get http response
let observer = new IntersectionObserver(function(e){ // element enter or leave will trigger this function
// console.log('e :>> ', e[0]);
if(e[0].isIntersecting){ //if visible
request();
}
})
observer.observe(loading); // observe loading element visible
window.onload = function() {
rendering(5); // first page
}
function request(){
let childrenLength = Array.from(outer.children).filter(it => it.className === 'inner').length;
requestFlag = true;
setTimeout(() => {// simulate request
requestFlag = false;
if(childrenLength >= 30){ // max data size
requestFlag = true; // all data return ,never set requestFlag false again
loading.textContent = 'all return';
observer.disconnect(); // close IntersectionObserver
return
}
outer.removeChild(loading); // remove loading element
rendering(5);
}, 1000);// delay 1s to simulate request
}
/**
* append child
*/
function rendering(size){
for (let i = 0; i < size; i++) {
let div = document.createElement('div');
div.classList.add('inner');
div.textContent = i;
div.style.backgroundColor = `rgb(${parseInt(Math.random()*255)},${parseInt(Math.random()*255)},${parseInt(Math.random()*255)})`;
outer.appendChild(div);
}
outer.appendChild(loading);
}
</script>
</html>
效果
滚到底部,1秒延时后加载
若有错误/补充,敬请指出更改