前言
开发过程中,通常会碰到大量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);
});