DocumentFragment
DocumentFragment
,文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的 Document 使用,就像标准的document一样,存储由节点(nodes)组成的文档结构。与document相比,最大的区别是DocumentFragment 不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染,且不会导致性能等问题。
最常用的方法是使用文档片段作为参数(例如,任何 Node 接口类似 Node.appendChild 和 Node.insertBefore 的方法),这种情况下被添加(append)或被插入的是片段的所有子节点, 而非片段本身。因为所有的节点会被一次插入到文档中,而这个操作仅发生一个重渲染的操作,而不是每个节点分别被插入到文档中,因为后者会发生多次重渲染的操作。他就相当于一个虚拟的包裹器 类似于React的 <></>
和vue的<template></template>
,它本身不会存在于DOM树中
注: 如果使用appendChid方法将原dom树中的节点添加到DocumentFragment中时,在插入时会先在文档树中删除该节点,然后再将其插入到指定节点。
多的不说 上测试
测试
需求 : 页面现有一个列表 需要动态添加3000个<li>
进去 我们分别测试渲染所需要时间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>documentFragment</title>
</head>
<body>
<button onclick="useAppend()">使用appendChild添加</button>
<button onclick="useFragment()">使用fragment添加</button>
<ul id="list"></ul>
<script>
const list = document.querySelector('#list')
const listItem = Array(3000).fill('我是一个li')
function useAppend() {
const ts = window.performance.now()
listItem.forEach(i => {
const li = document.createElement('li')
li.innerText = i
list.appendChild(li)
})
const te = window.performance.now()
console.log(`使用appendChild渲染花费了${te - ts} 毫秒`)
}
function useFragment() {
const ts = window.performance.now()
const fragment = document.createDocumentFragment()
listItem.forEach(i => {
const li = document.createElement('li')
li.innerText = i
fragment.appendChild(li)
});
const te = window.performance.now()
list.appendChild(fragment)
console.log(`使用documentFragment渲染花费了${te - ts} 毫秒`)
}
</script>
</body>
</html>
看结果
渲染时间相差接近一倍