# 1.大数据列表渲染的优化
# 大数据列表的渲染怎么优化?
# setTimeout/requestAnimationFrame 时间切片
- 通过 setTimeout 或 requestAnimationFrame 将渲染任务分解为多个小任务,每个小任务在一个帧或者一个空闲时段内完成。这样可以避免长时间的任务阻塞页面,提高页面的响应性。但是,使用 setTimeout 的方法在快速滑动时可能会引起白屏。
# DocumentFragment 文档切片
- 是 DOM 节点,但不是真实 DOM 树,子元素插入不会引起页面重排
- 适用于 DOM 结构简单情况
# 使用虚拟列表
- 只展示可视区域的节点内容:结合 slice、computed 计算属性
- 缺点是什么,该怎么改善
- 频繁计算Dom节点,短暂的白屏
- 解决方案:预加载。跟小红书的翻页类似
简单实现
<template>
<div class="virtual-list" ref="list" @scroll="scrollHandler">
<div class="phantom" :style="{ height: totalHeight + 'px' }"></div>
<div class="list-viewport" :style="{ transform: `translate3d(0, ${startOffset}px, 0)` }">
<div v-for="(item, index) in visibleItems" :key="index">
<!-- Render your item -->
<div>{{ item }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
listHeight: 0,
scrollY: 0,
itemHeight: 50,
items: Array.from({ length: 10000 }, (_, i) => `Item ${i}`), // Replace with your data
};
},
computed: {
visibleCount() {
return Math.ceil(this.listHeight / this.itemHeight);
},
startIndex() {
return Math.floor(this.scrollY / this.itemHeight);
},
endIndex() {
return Math.min(this.startIndex + this.visibleCount + 1, this.items.length);
},
visibleItems() {
return this.items.slice(this.startIndex, this.endIndex);
},
startOffset() {
return this.startIndex * this.itemHeight;
},
totalHeight() {
return this.items.length * this.itemHeight;
},
},
methods: {
scrollHandler(e) {
this.scrollY = e.target.scrollTop;
},
},
mounted() {
this.listHeight = this.$refs.list.clientHeight;
},
};
</script>
<style scoped>
.virtual-list {
overflow-y: auto;
height: 100%; /* Adjust based on your need */
}
.phantom {
visibility: hidden;
}
.list-viewport {
position: absolute;
width: 100%;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 使用 IntersectionObserver 替换 scroll 事件
IntersectionObserver
是一种可以监听元素是否进入视口的 API。相比于 scroll 事件,IntersectionObserver
更加高效,因为它是由浏览器在后台线程中执行的,不会阻塞主线程。我们可以使用 IntersectionObserver 来判断哪些元素进入了视口,然后只渲染这些元素,提高性能。