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>

看结果

image.png

image.png

渲染时间相差接近一倍

目录