all
You must replace the baseURL in hugo.toml file when deploying, you can manage this announcement from the params.toml file.

DOM-文档片段

  • May 23, 2016
内容列表

DOM 操作是非常消耗性能的,如果要进行大量的 DOM 操作,我们可以选择在内存中先构建一个文档片段然后一次性插入 DOM 树。

文档片段

文档片段(DocumentFragment)也就是 DOM 树的部分节点组合而成的局部。频繁的 DOM 操作对性能的影响是显著的,如果我们要进行大量的相似的 DOM 操作,建议在内存中创建一个文档片段并对其修饰,然后一次性插入 DOM 树。这么做的对性能的影响是最小的,同时也更灵活一些。

创建文档片段

创建的文档片段是存放在内存中的,我们要谨慎操作,以防丢失引用或者内存泄漏,集中处理完毕后要及时更新到 DOM 树上。

  • createDocumentFragment()

exp:

<script>
    var docFrag = document.createDocumentFragment();

    ['blue','green','red','pink'].forEach(function(e){
        var li = document.createElement('li');
        li.textContent = e;
        li.style.backgroundColor = e;
        docFrag.appendChild(li);
    });
</script>

这样,我们就创建好了一个文档片段,其中包含了四个 li 元素,我们并把它们各自的背景色设置为了其文本内容。

更新到 DOM 树

在内存中对文档片段处理完毕后,我们就应该将其更新到 DOM 树上,采用的方法前面已经介绍过了。

  • appendChild()
  • insertBefore()

exp:

<body>
    <ul id="container"></ul>
    <script>
        document.getElementById('container').appendChild(docFrag);
    </script>
</body>

这样我们就将刚才创建的文档片段插入到了 DOM 树中,在页面上的效果也是我们预期的。要清楚的是,文档片段被插入 DOM 树中时,自身会被选中的 DOM 元素替代,也就是文档片段内的元素全都作为选中元素的子元素插入;而且,在插入 DOM 树后,文档片段自身也不再存在,不会发生内存泄漏的问题。

更灵活的做法

为了让创建文档片段结构更加灵活一点,我们可以使用节点的属性来快速创建 DOM 结构。

  • innerHTML

exp:

<body>
    <script>
        var docFrag = document.createDocumentFragment();
        var divO = document.createElement('div');

        docFrag.appendChild(divO);
        docFrag.querySelector('div').innerHTML = "<ul><li>1</li><li>2</li><li>3</li></ul>";

        document.getElementById('container').appendChild(docFrag);
    </script>
</body>

该方法用来创建更复杂的 DOM 结构的代码量是很少的,所以说创建文档片段可以混合不同的方法来提高效率,当然该方法可能更耗性能一些。

重复利用

我们前面说过,文档片段在更新到 DOM 树中时会自动消失,如果我们想重复利用文档片段的话,在插入 DOM 树时将其副本插入就可以了。

  • cloneNode()

注意,cloneNode() 方法有一个布尔型参数,false 代表只复制节点自身,true 代表复制节点自身及其所有子节点。

结语

文档片段为我们提供了一个在内存中进行 DOM 预处理的机制,这要比我们重复进行真实 DOM 操作性能要高得多,我们应该合理利用这个机制。

参考

  • 《DOM 启蒙》,Cody Lindley,陈养剑 译
comments powered by Disqus

相关

解析基于 core-js 与 ESLint 的 Web 兼容方案

Web 网页为了保证在多个平台和低中高端设备上的体验稳定性和一致性,通常会做 Polyfill 以保证兼容性。

了解更多

Web 前端性能优化:批量 DOM 操作 - FastDOM

利用 JS 开发的原生应用与依赖于 React.js/Vue 开发的框架/库应用,性能孰高孰低?这两者最显著的区别在于原生应用需要手动操作 DOM 完成业务,而框架/库应用是基于数据变化响应式的应用,后者只需要关注数据如何变化,至于体现在 DOM 上的变化皆由框架/库内部自动完成。所以,要搞清楚两者的性能优劣,可能批量的 DOM 操作是一个不可忽略的核心因素。从代码执行的角度分析,框架/库也是基于原生 API 进行的封装抽象,因此代码执行时的路径更长、堆栈更深,由此可见原生 API 的操作性能应该是最高的。但是,现实情况是业务通常来说是复杂的,代码实现中 DOM 操作的逻辑分散在各处,那么多个 DOM 操作之间是否会产生影响从而不利于性能?这个时候就要关注宿主浏览器的渲染机制是如何理解批量的 DOM 操作的,这里引入的概念就是关键渲染路径(Critical rendering path)

了解更多

DOM-节点集合

当从文档树中选取成组的节点或者使用预定义的节点集合时,这些节点都是放在 NodeList 或者一个 HTMLCollecton 之中,而不是一个数组(Array)中。

了解更多