性能优化 - 分片渲染

开发 · 2023-10-18 · 40 人浏览

前言

开发过程中,通常会碰到大量DOM渲染的场景,如万级以上的数据渲染就会开始卡的飞起,针对此列情况列出常见的第一种优化方案:分片渲染

// 一次性渲染
<ul id="container"></ul>
const total = 100000;
let ul = document.getElementById('container')
for (let i = 0; i < pageCount; i++) {
      let li = document.createElement("li");
      li.innerText = ~~(Math.random() * total);
      ul.appendChild(li);
}

技巧

该方案下我们需要用到requestAnimationFrame,不同于setTimeout,它会随着系统为我们提供更加流畅的动画表现,
以及DocumentFragment,作为一个内存的DOM片段,它不会去计算其中的样式表消耗,尽管现代浏览器本身优化就已经做的很好了(样式表的计算推到脚本执行之后),这里能做到的优化都会做上。

原理

本质来说和触底滚动加载,以及分页原理一样,这里只是换成了切片渲染,殊途同归都是为了解决线程互斥的问题,通过减少渲染线程的消耗,降低用户的卡顿感

实现

<ul ref="con"></ul>
import { ref, onMounted } from "vue";

const total = 100000; //10W 条
let once = 20; // 一次插入20条
let index = 0; //页数
// 获取容器
let con = ref(null);

function loopGUI(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.innerText = curIndex + i + ":" + ~~(Math.random() * total);
      fragment.appendChild(li);
    }
    con.value.appendChild(fragment);
    // 递归,每渲染一次后自动计算下一次要渲染的条数和索引
    loopGUI(curTotal - pageCount, curIndex + pageCount);
  });
}
onMounted(() => {
  loopGUI(total, index);
});
性能优化 时间分片
Theme Jasmine by Kent Liao