js实现前端⽆限滚动中的虚拟列表效果(只渲染可视区域,dom元素可复⽤)先看效果
不加防抖节流。
加防抖节流
提⽰
加防抖节流 可以节省性能,但滑动过快会出现闪烁现象。请根据需求⾃⾏调整触发时间。原理通过代码可看出!
限制:该代码处理⽅式由于html 元素⾼度存在最⼤值,且不同浏览器以及不同浏览器版本⽀持的html 元素⾼度最⼤值不⼀样,当数据列表理论⽣成的⾼度⼤于html元素⾼度最⼤值时,⽣成的滚动区域只有html元素⾼度最⼤值那部分,剩下部分⽆法显⽰出来。
代码
不加防抖节流
<!DOCTYPE html>
<html lang="en">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>⽆限滚动中的虚拟列表(只渲染可视区域,dom元素可复⽤)</title>
<meta name="viewport" content="initial-scale=1.0">
<meta name="format-detection" content="telephone=no, email=no">
</head>
<body>
<header>
<!--<h1>⽆限滚动中的虚拟列表-防抖和节流(只渲染可视区域,dom元素可复⽤)</h1>-->
<h1>⽆限滚动中的虚拟列表(只渲染可视区域,dom元素可复⽤)</h1>
</header>
</article>
<article class="d-part d-effect">
<style>
.container {
height:600px;
overflow: auto;
}
.item {
min-height:60px;
border-bottom:1px solid #cccccc;
border-top:1px solid #cccccc;
width:100%;
text-align: center;
background-color: darkgray;
/* padding: 30px 0;
box-sizing: border-box; */
}
</style>
<div class="container">
<div class="content">
<div class="viewArea">
<div class="item">0</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</div>
</div>
<script>
var item = document.querySelector('.viewArea .item');//需要渲染的单个列表元素
var container = document.querySelector('.container');//可视区域元素
console.log(item);
var start =0;// 开始位置
var pageSize =10;// 每页展⽰的数据
var total =100000;//数据总长度
// var itemHeight = 61; // 每个item的⾼度
var itemStyle =getComputedStyle(item);// 获取元素最终样式
var itemHeight =Number(itemStyle.height.split('px')[0])+Number(itemStyle.borderTopWidth.split('px')[0])+Number(itemStyle.borderBottomWidth.s plit('px')[0]);// 每个item的⾼度
console.log('itemHeight', itemHeight);
// 设置数据列表的总⾼度
document.querySelector('.container .content').style.height = itemHeight * total +'px';
updateDom(start, pageSize, itemHeight,0);
//更新渲染列表函数
function updateDom(start, pageSize, itemHeight, height){
document.querySelector('.container .content .viewArea').ansform ='translateY('+ height +'px)';
let all = document.querySelectorAll(' .viewArea .item');// 获取所有渲染列表
for(var i = start, itemIndex =0, len = start + pageSize; i < len; i++, itemIndex++){
var index = i % pageSize;// 计算出数据列表的下标
all[itemIndex].innerHTML = i;
}
}
// 滚动处理函数
function handleScroller(){
var lastStart =0;// 上次开始的位置
return()=>{
var currentScrollTop = container.scrollTop;
var fixedScrollTop = currentScrollTop - currentScrollTop % itemHeight;
var start = Math.floor(currentScrollTop / itemHeight);
if(lastStart !== start){
lastStart = start;
updateDom(start, pageSize, itemHeight, fixedScrollTop);
}
}
}
/
/ // 防抖和节流
// function throttle(fn, delay, atleast) {
// let timer = null;
// let rAFtimer = null;
// let previous = 0;
// return function () {
// let now = w();
// if (now - previous > atleast) {
// console.log('now - previous > atleast');
// fn();
// previous = now;
/
/ } else {
// if (delay > 20) {
// console.log('delay > 20');
// clearTimeout(timer);
// timer = setTimeout(function () {
// fn();
// previous = 0;
// }, delay);
// } else {
// console.log('delay < 20');
// cancelAnimationFrame(rAFtimer);
/
/ rAFtimer = requestAnimationFrame(function () {
// requestIdleCallback(fn);
// });
// }
// }
// }
// }
// document.querySelector('.container').addEventListener('scroll', throttle(handleScroller(), 16, 500), false); document.querySelector('.container').addEventListener('scroll',handleScroller(),false);
</script>
</article>
</div>
</body>
</html>
</html>
加防抖节流
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>⽆限滚动中的虚拟列表(只渲染可视区域,dom元素可复⽤)</title>
<meta name="viewport" content="initial-scale=1.0">
<meta name="format-detection" content="telephone=no, email=no">
</head>
<body>
<header>
<h1>⽆限滚动中的虚拟列表-防抖和节流(只渲染可视区域,dom元素可复⽤)</h1> <!--<h1>⽆限滚动中的虚拟列表(只渲染可视区域,dom元素可复⽤)</h1>-->
</header>
</article>
<article class="d-part d-effect">
<style>
.container {
height:600px;
overflow: auto;
}
.item {
min-height:60px;
border-bottom:1px solid #cccccc;
border-top:1px solid #cccccc;
width:100%;
text-align: center;
background-color: darkgray;
/* padding: 30px 0;
box-sizing: border-box; */
}
</style>
<div class="container">
<div class="content">
<div class="viewArea">
<div class="item">0</div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</div>
</div>
<script>
var item = document.querySelector('.viewArea .item');
var container = document.querySelector('.container');
console.log(item);
var start =0;// 开始位置
var pageSize =10;// 每页展⽰的数据
var total =100000;//数据总长度
// var itemHeight = 61; // 每个item的⾼度
var itemStyle =getComputedStyle(item);
var itemStyle =getComputedStyle(item);
var itemHeight =Number(itemStyle.height.split('px')[0])+Number(itemStyle.borderTopWidth.split('px')[0])+Number(itemStyle.borderBottomWidth.s plit('px')[0]);// 每个item的⾼度
console.log('itemHeight', itemHeight);
// 设置数据列表的总⾼度
document.querySelector('.container .content').style.height = itemHeight * total +'px';
updateDom(start, pageSize, itemHeight,0);
function updateDom(start, pageSize, itemHeight, height){
document.querySelector('.container .content .viewArea').ansform ='translateY('+ height +'px)';
let all = document.querySelectorAll(' .viewArea .item');
for(var i = start, itemIndex =0, len = start + pageSize; i < len; i++, itemIndex++){
var index = i % pageSize;
all[itemIndex].innerHTML = i;
}
}
// 滚动处理函数
function handleScroller(){
var lastStart =0;// 上次开始的位置
return()=>{
var currentScrollTop = container.scrollTop;
var fixedScrollTop = currentScrollTop - currentScrollTop % itemHeight;
var start = Math.floor(currentScrollTop / itemHeight);
if(lastStart !== start){
lastStart = start;
updateDom(start, pageSize, itemHeight, fixedScrollTop);
}
}
}
// 防抖和节流
function throttle(fn, delay, atleast){
let timer =null;
let rAFtimer =null;
let previous =0;
return function(){
let now = w();
if(now - previous > atleast){
console.log('now - previous > atleast');
fn();
previous = now;
}else{
if(delay >20){
console.log('delay > 20');
clearTimeout(timer);
timer =setTimeout(function(){
fn();
previous =0;
}, delay);
}else{
console.log('delay < 20');
cancelAnimationFrame(rAFtimer);
rAFtimer =requestAnimationFrame(function(){
requestIdleCallback(fn);
});
}
}
}
}
document.querySelector('.container').addEventListener('scroll',throttle(handleScroller(),16,500),false);
// document.querySelector('.container').addEventListener('scroll', handleScroller(), false);
borderbox</script>
</article>
</div>
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论