# 1.大数据列表渲染的优化

# 大数据列表的渲染怎么优化?

# setTimeout/requestAnimationFrame 时间切片

  1. 通过 setTimeout 或 requestAnimationFrame 将渲染任务分解为多个小任务,每个小任务在一个帧或者一个空闲时段内完成。这样可以避免长时间的任务阻塞页面,提高页面的响应性。但是,使用 setTimeout 的方法在快速滑动时可能会引起白屏。

# DocumentFragment 文档切片

  1. 是 DOM 节点,但不是真实 DOM 树,子元素插入不会引起页面重排
  2. 适用于 DOM 结构简单情况

# 使用虚拟列表

  1. 只展示可视区域的节点内容:结合 slice、computed 计算属性
  2. 缺点是什么,该怎么改善
    1. 频繁计算Dom节点,短暂的白屏
    2. 解决方案:预加载。跟小红书的翻页类似

简单实现

<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

# 使用 IntersectionObserver 替换 scroll 事件

  1. IntersectionObserver 是一种可以监听元素是否进入视口的 API。相比于 scroll 事件,IntersectionObserver 更加高效,因为它是由浏览器在后台线程中执行的,不会阻塞主线程。我们可以使用 IntersectionObserver 来判断哪些元素进入了视口,然后只渲染这些元素,提高性能。
Last Updated: 6/3/2024, 1:08:34 AM