先看效果
不加防抖节流。 加防抖节流 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200827094205237.gif#pic_center)
提示
加防抖节流 可以节省性能,但滑动过快会出现闪烁现象。请根据需求自行调整触发时间。原理通过代码可看出!
限制:该代码处理方式由于html 元素高度存在最大值,且不同浏览器以及不同浏览器版本支持的html 元素高度最大值不一样,当数据列表理论生成的高度大于html元素高度最大值时,生成的滚动区域只有html元素高度最大值那部分,剩下部分无法显示出来。
代码
不加防抖节流
无限滚动中的虚拟列表(只渲染可视区域,dom元素可复用)
无限滚动中的虚拟列表(只渲染可视区域,dom元素可复用)
.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; */
}
0
1
2
3
4
5
6
7
8
9
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.split('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').style.transform = 'translateY(' + height + 'px)';
let all = document.querySelectorAll(' .viewArea .item'); // 获取所有渲染列表
for (var i = start, itemIndex = 0, len = start + pageSize; i {
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 = Date.now();
// 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);
加防抖节流
无限滚动中的虚拟列表(只渲染可视区域,dom元素可复用)
无限滚动中的虚拟列表-防抖和节流(只渲染可视区域,dom元素可复用)
.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; */
}
0
1
2
3
4
5
6
7
8
9
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.split('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').style.transform = 'translateY(' + height + 'px)';
let all = document.querySelectorAll(' .viewArea .item');
for (var i = start, itemIndex = 0, len = start + pageSize; i {
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 = Date.now();
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);
|