startIndex = 0
当前加载个数 = Math.ceil(可视区域高度 / 每列高度)
endIndex = startIndex + count
占位高度 = 数据总个数 * 每列高度
listData
:list.slice(startIndex, endIndex)
onscroll
事件
startIndex = Math.floor(滚动条距离 / 每列高度)
endIndex = startIndex + count
listData
transform: transform3d(0, startIndex * 每列高度)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
.list-view {
height: 400px;
position: relative;
overflow-y: auto;
}
.zhanwei {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
}
.list-content li {
height: 100px;
}
/* .list-content li:nth-of-type(odd) {
background: #00ccff;
}
.list-content li:nth-of-type(even) {
background: #ffcc00;
} */
.list-content li {
background: #ffcc00;
}
</style>
</head>
<body>
<!-- 可视区 -->
<div id="listView" class="list-view">
<!-- 占位高度 -->
<div id="zhanwei" class="zhanwei"></div>
<!-- 实际列表 -->
<ul id="listContent" class="list-content"></ul>
</div>
<script>
let temp = 3;
// 模拟长列表的数据
function setLongData() {
let data = [];
for (let i = 0; i < 1000000; i++) {
data.push({ id: "item" + i });
}
return data;
}
function selectDom(selector) {
return document.querySelector(selector);
}
// 加载数据并插入DOM到页面
function loadData(start, end) {
// 截取数据
let sliceData = setLongData().slice(start, end);
// 创建虚拟DOM
let F = document.createDocumentFragment();
for (let i = 0; i < sliceData.length; i++) {
let li = document.createElement("li");
li.innerText = JSON.stringify(sliceData[i]);
li.className = sliceData[i].id;
F.appendChild(li);
}
selectDom(".list-content").innerHTML = "";
selectDom(".list-content").appendChild(F);
}
// 设置占位DOM的高度
document.getElementById("zhanwei").style.height = `${
100 * setLongData().length
}px`;
// 计算可视区能展示几列数据,此处假设一列的高度为 100 px
let count = Math.ceil(document.body.clientHeight / 100);
console.log(document.body.clientHeight);
let startIndex = 0; // 可视区第一列的索引
let endIndex = count; // 可视区最后一列的索引
loadData(startIndex, endIndex);
// 滚动加载数据方法
function scrollFunction() {
// 获取滚动条距离可视区顶部的距离
let scrollTop = document.getElementById("listView").scrollTop;
startIndex = Math.floor(scrollTop / 100);
endIndex = startIndex + count;
loadData(startIndex, endIndex);
// 滚动时内容区会发生偏移
// 通过 transform:translate3d将偏移的内容移回可视区
document.getElementById(
"listContent"
).style.transform = `translate3d(0, ${startIndex * 100}px, 0)`;
}
document
.getElementById("listView")
.addEventListener("scroll", scrollFunction);
</script>
</body>
</html>
https://github.com/chenqf/frontEndBlog/issues/16
俩 demo: