前言
在javascript中每当对DOM进行一次操作如插入删除元素,会触发浏览器重新解析和渲染。对DOM反复操作会导致页面重绘、回流,效率非常低,并且页面可能会被卡死。
当你需要一次性进行多次DOM插入操作时,使用DocumentFragment可以减少浏览器重新解析。
说明
DocumentFragment(文档片段)是DOM节点。它们不是主DOM树的一部分。使用方法是创建DocumentFragment,将元素附到DocumentFragment,再把DocumentFragment附到DOM树节点上。
在DOM树中,DocumentFragment被它所有子元素代替。DocumentFragment是在内存中创建,并不在DOM树中,因此把子元素插入到DocumentFragment时不会引起页面回流(reflow),所以使用DocumentFragment会带来更好的性能。
示例
例如你在项目中需要在ul中插入100000个li。
<ul id="ul"></ul>
优化前
常用的方法是逐项插入,代码如下:
function addList() {
console.time("addList");
let ul = document.getElementById("ul");
let li = null;
for (let i = 0; i < 100000; i++) {
li = document.createElement("li");
li.appendChild(document.createTextNode("li" + (i + 1)));
ul.appendChild(li);
}
console.timeEnd("addList");
}
addList();
优化后
使用DocumentFragment方法,代码如下:
function addListByFragment() {
console.time("addListByFragment");
let ul = document.getElementById("ul");
let li = null;
let fragment = document.createDocumentFragment();
for (let i = 0; i < 100000; i++) {
li = document.createElement("li");
li.appendChild(document.createTextNode("li" + (i + 1)));
fragment.appendChild(li);
}
ul.appendChild(fragment);
console.timeEnd("addListByFragment");
}
addListByFragment();
执行结果耗时比较
其他方法
拼接html字符串,使用innerHTML替换掉容器内的标签内容
function addListByHTML() {
console.time("addListByHTML");
let ul = document.getElementById("ul");
let strHtml = '';
for (let i = 0; i < 100000; i++) {
strHtml+=`<li>li ${i + 1}</li>`;
}
ul.innerHTML = strHtml;
console.timeEnd("addListByHTML");
}
addListByHTML();
在setTimeout 进行DOM操作
function addListByTimeout() {
setTimeout(() => {
console.time("addListByTimeout");
let ul = document.getElementById("ul");
let li = null;
let fragment = document.createDocumentFragment();
for (let i = 0; i < 100000; i++) {
li = document.createElement("li");
li.appendChild(document.createTextNode("li" + (i + 1)));
fragment.appendChild(li);
}
ul.appendChild(fragment);
console.timeEnd("addListByTimeout");
}, 0)
}
addListByTimeout();
setTimeout分段添加
function addListByStep() {
let i = 0;
setTimeout(function addNodes() {
console.time("addListByStep");
for (let step = i + 500; i < step; i++) {
let li = document.createElement('li');
li.appendChild(document.createTextNode('li' + (i + 1)));
ul.appendChild(li);
}
console.timeEnd("addListByStep");
if (i < 100000) {
setTimeout(addNodes, 0);
}
}, 0);
}
addListByStep();
由于分段添加每一次的耗时较短,感观上不会造成页面卡死,可以进行页面其他操作。
总结
向DOM添加元素有逐项插入法,innerHTML属性赋值替换法,DocumentFragment文档片段一次性添加法,setTimeout分段添加法。
以上就是关于DocumentFragment用法的用法,下次当你有需要添加DOM时,可以尝试用上它。