闽公网安备 35020302035485号
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="ul"></ul>
<script>
let now = Date.now(); //Date.now()得到时间戳
const total = 100000
const ul = document.getElementById('ul')
for (let i = 0; i < total; i++) {
let li = document.createElement('li')
li.innerHTML = ~~(Math.random() * total)
ul.appendChild(li)
}
console.log('js运行时间',Date.now()-now);
setTimeout(()=>{
console.log('总时间',Date.now()-now);
},0)
console.log();
</script>
</body>
</html>
运行可以看到这个数据:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>堆代码 duidaima.com</title>
</head>
<body>
<ul id="ul"></ul>
<script>
let now = Date.now(); //Date.now()得到时间戳
const total = 100000 //总共100000条数据
const once = 20 //每次插入20条
const page = total / once //总页数
let index = 1
const ul = document.getElementById('ul')
function loop(curTotal, curIndex) {
if (curTotal <= 0) { 判断总数居条数是否小于等于0
return false
}
let pageCount = Math.min(curTotal, once) //以便除不尽有余数
setTimeout(() => {
for (let i = 0; i < pageCount; i++) {
let li = document.createElement('li')
li.innerHTML = curIndex + i + ':' + ~~(Math.random() * total)
ul.appendChild(li)
}
loop(curTotal - pageCount, curIndex + pageCount)
}, 0)
}
loop(total, index)
</script>
</body>
</html>
运行后可以看到这十万条数据并不是一次性全部加载出来,浏览器右方的下拉条有顺滑的效果哦,如下图:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<ul id="ul"></ul>
<script>
let now = Date.now(); //Date.now()得到时间戳
const total = 10000
const once = 20
const page = total / once
let index = 1
const ul = document.getElementById('ul')
function loop(curTotal, curIndex) {
if (curTotal <= 0) {
return false
}
let pageCount = Math.min(curTotal, once) //以便除不尽有余数
requestAnimationFrame(()=>{
let fragment = document.createDocumentFragment() //虚拟文档
for (let i = 0; i < pageCount; i++) {
let li = document.createElement('li')
li.innerHTML = curIndex + i + ':' + ~~(Math.random() * total)
fragment.appendChild(li)
}
ul.appendChild(fragment)
loop(curTotal - pageCount, curIndex + pageCount)
})
}
loop(total, index)
</script>
</body>
</html>
可以看到它白屏时间没有那么长了:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<title>虚拟列表</title>
<style>
.v-scroll {
height: 600px;
width: 400px;
border: 3px solid #000;
overflow: auto;
position: relative;
-webkit-overflow-scrolling: touch;
}
.infinite-list {
position: absolute;
left: 0;
top: 0;
right: 0;
z-index: -1;
}
.scroll-list {
left: 0;
right: 0;
top: 0;
position: absolute;
text-align: center;
}
.scroll-item {
padding: 10px;
color: #555;
box-sizing: border-box;
border-bottom: 1px solid #999;
}
</style>
</head>
<body>
<div id="app">
<div ref="list" class="v-scroll" @scroll="scrollEvent($event)">
<div class="infinite-list" :style="{ height: listHeight + 'px' }"></div>
<div class="scroll-list" :style="{ transform: getTransform }">
<div ref="items" class="scroll-item" v-for="item in visibleData" :key="item.id"
:style="{ height: itemHeight + 'px',lineHeight: itemHeight + 'px' }">{{ item.msg }}</div>
</div>
</div>
</div>
<script>
var throttle = (func, delay) => { //节流
var prev = Date.now();
return function () {
var context = this;
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
let listData = []
for (let i = 1; i <= 10000; i++) {
listData.push({
id: i,
msg: i + ':' + Math.floor(Math.random() * 10000)
})
}
const { createApp } = Vue
createApp({
data() {
return {
listData: listData,
itemHeight: 60,
//可视区域高度
screenHeight: 600,
//偏移量
startOffset: 0,
//起始索引
start: 0,
//结束索引
end: null,
};
},
computed: {
//列表总高度
listHeight() {
return this.listData.length * this.itemHeight;
},
//可显示的列表项数
visibleCount() {
return Math.ceil(this.screenHeight / this.itemHeight)
},
//偏移量对应的style
getTransform() {
return `translate3d(0,${this.startOffset}px,0)`;
},
//获取真实显示列表数据
visibleData() {
return this.listData.slice(this.start, Math.min(this.end, this.listData.length));
}
},
mounted() {
this.start = 0;
this.end = this.start + this.visibleCount;
},
methods: {
scrollEvent() {
//当前滚动位置
let scrollTop = this.$refs.list.scrollTop;
//此时的开始索引
this.start = Math.floor(scrollTop / this.itemHeight);
//此时的结束索引
this.end = this.start + this.visibleCount;
//此时的偏移量
this.startOffset = scrollTop - (scrollTop % this.itemHeight);
}
}
}).mount('#app')
</script>
</body>
</html>
可以看到白屏现象解决了!