js实现长列表渲染
众所周知,DOM多了之后,页面会变得很卡顿。有时候又不得不渲染很多数据,比如长列表,这时就需要前端做一些渲染优化了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
div,
ul,
li {
box-sizing: border-box;
}
ul,
li {
list-style: none;
}
.scroll {
margin: 50px auto;
width: 500px;
height: 300px;
overflow-y: auto;
background-color: pink;
}
.item {
width: 100%;
height: 50px;
border: 1px solid #b2ceeb;
margin-bottom: 5px;
}
.item:last-child {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="scroll">
<ul class="container"></ul>
</div>
</body>
</html>
<script>
// 获取滚动元素和列表容器元素
const scrollEle = document.querySelector(".scroll");
const containEle = document.querySelector(".container");
const scrollArea = scrollEle.clientHeight; // 可视区域的高度
const itemH = 50; // 每一个项目的高度(定高)
const size = Math.ceil(scrollArea / itemH); // 可视区域能展示的条数
// 初始化数据列表
const dataList = new Array(10000);
function scrollFn() {
const scrollTop = scrollEle.scrollTop; // 获取滚动距离
const first = Math.floor(scrollTop / itemH); // 根据滚动距离和列表高度计算出当前视图中第一条数据的索引
const end = first + size; // 计算视图中最后一条数据的索引
const data = dataList.slice(first, end); // 根据索引截取视图所展示的数据
// 拼装截取的数据
let box = "";
for (let i = 0; i < data.length; i++) {
box += `<li class="item">${first + 1 + i}</li>`;
}
containEle.innerHTML = box; // 内容替换
// 通过给列表容器设置padding值来保证滚动条的位置正确
const paddingTop = first * itemH;
const paddingBottom = (dataList.length - end) * itemH;
containEle.setAttribute(
"style",
`padding-top: ${paddingTop}px; padding-bottom: ${paddingBottom}px`
);
}
document.onload = scrollFn(); // 初始化渲染
scrollEle.onscroll = scrollFn;
</script>
上面这种方式只是适用于数据是一次性给的情况。其实我个人觉得,数据多了最好和后端协商一下,让后端做分页处理。全靠前端的话,局限性比较大。哪怕做了虚拟列表处理,数据过大的情况下,还是展示不全。
目前我测试过的谷歌浏览器的页面的最大宽/高是33554400px,如果超过这个宽度/高度,会被默认切掉。