在高度固定且可滚动的容器内渲染有限数量的节点。
height:500px;overflow:auto
的容器内,假如每行节点height:50px
,那么10行
这样的节点便可填满容器。- 每行节点
height:50px
,假如有1000行
这样的节点,那么,全部节点的高度和便是50*1000=50000px
,这足以撑开容器得到滚动条。 - 监听容器的
scroll
事件,可获取滚动的垂直距离srollTop
,从而计算出此时应该渲染第几行节点。 - 如果滚动过快,可能会出现闪烁,可预先渲染几行,比如,
10行
高50px
的节点可填满高500px
的固定容器,那么一开始就渲染12行
或15行
。 - 为避免快速滚动导致的频繁渲染,可通过节流来控制渲染速率。
<body>
<div class="container">
<ul class="content"></ul>
</div>
</body>
.container{
width: 500px;
height: 500px;
border: 2px solid lightskyblue;
overflow:auto;
}
.content{
list-style: none;
padding:0;
margin:0;
font-weight: bold;
box-sizing:border-box;
}
li{
height:50px;
line-height: 50px;
}
li:nth-child(even){
background-color:lightgoldenrodyellow
}
li:nth-child(odd){
background-color: lightcyan;
}
const LEN = 1000;
const HEIGHT = 50;
const TOTAL_HTIGHT = LEN*HEIGHT;
var content = document.querySelector(".content");
content.style.height = TOTAL_HTIGHT + "px";
var startIndex = 0;
var endIndex = 15;
var list = initList();
var visibleList = list.slice(startIndex,endIndex);
content.innerHTML = visibleList.join(" ");
var container = document.querySelector(".container");
// container.addEventListener("scroll",loadVisibleList);
container.addEventListener("scroll", throttle(loadVisibleList));
// container.addEventListener("scroll",throttle_raf(loadVisibleList));
function initList(){
const list = [];
for(var i=0;i<LEN;i++){
var liElm = `<li>${i+1}</li>`;
list.push(liElm);
}
return list;
}
function loadVisibleList(){
var scrollTop = container.scrollTop;
content.innerHTML = "";
startIndex = Math.floor(scrollTop/HEIGHT);
content.style.paddingTop = startIndex * HEIGHT+"px";
endIndex = startIndex+15;
visibleList = list.slice(startIndex,endIndex).join(" ");
content.innerHTML = visibleList;
console.log("scroll");
}
// function throttle_raf(fn,context){
// var args = Array.prototype.slice.call(arguments,2);
// var requestId = null;
// return function(){
// if(requestId!==null) return;
// var finalArgs = args.concat(Array.prototype.slice.call(arguments));
// requestId = requestAnimationFrame(() => {
// fn.apply(context,finalArgs);
// requestId = null;
// });
// }
// }
function throttle(fn,context,delay=100){
var args = Array.prototype.slice.call(arguments,3);
var timer = null;
return function(){
if(timer!=null) return;
var finalArgs = args.concat(Array.prototype.slice.call(arguments));
timer = setTimeout(() => {
fn.apply(context,finalArgs);
timer = null;
},delay);
}
}