先来看效果
不多说,开撸···
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="content" style="height: 80vh; width: 300px; background: lightblue; padding: 0 10px; overflow-y: auto;">
</div>
<script>
(() => {
let dom = "#content";// 父盒子dom
let bottomContactDistance = 100; // 触底距离
let page = 1; // 当前页码
let pageSize = 10; // 每页条数
let total = 24;
let dataList = [];
// 模拟数据
const list = Array.from(Array(total)).map((item, index) => {
return {
id: index,
name: 'name' + index,
}
});
// 模拟后台接口,返回 Promise
const dataApi = ({ page, pageSize }) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(list.slice(page, page + pageSize));
}, 1000);
})
}
// 获取数据
const getList = () => {
let params = { page: (page - 1) * pageSize, pageSize };
dataApi(params).then(res => {
console.log(params, res.map(it => it.id));
let el = document.querySelector(dom);
dataList = page == 0 ? res : dataList.concat(res);
if (page == 0) el.innerHTML = '';
res.map(item => {
let div = document.createElement('div');
div.style.height = '100px';
div.style.marginBottom = "10px";
div.style.background = 'lightgreen';
div.innerHTML = item.name;
el.appendChild(div)
})
})
}
// 在触发距离内滑动期间,本事件只会被触发一次
const onReachBottom = () => {
if (total <= dataList.length) return;
page++;
getList();
}
getList()
/* START: 监听固定区域内滚动事件 */
var content = document.querySelector(dom);
let flag = false;
content.addEventListener("scroll", function (e) {
let diff = content.scrollHeight - content.scrollTop - e.target.offsetHeight;
if (diff < bottomContactDistance) {
if (flag) return;
flag = true;
onReachBottom();
} else {
flag = false;
}
});
/* END: 监听固定区域内滚动事件 */
})();
</script>
</body>
</html>
特别说明
- 父盒子(本例中的#content)样式中需加
overflow-y: auto;
- 触发距离可以自行设置, 通过
bottomContactDistance
, 默认100px - 在触发距离内滑动期间,本事件只会被触发一次
- 本例中因后端的分页采用的是起止索引,因此page做了特殊处理