为什么说js中的Dom操作很慢

​ 之前看到说操作DOM很慢,要尽量少的去操作DOM。当时没有细究,以致于有时候写js还是会纠结,是直接操作DOM还是处理数据后refresh好一点。今天看到一篇文章,虽然还没能完全消化但也是学到不少,顺带着还get了Dev tools下的timeline的正确使用方式,在这里稍微整理一下:

一张页面是如何呈现出来的

简单来说,就是:

  1. 解析HTML,生成一棵DOM tree
  2. 解析css样式,结合DOM tree生成一棵Render tree
    render treeDOM tree并不完全对应,一个简单的例子就是display:none的元素虽然存在于DOM tree中,但是因为不需要被绘制所以不会出现在render tree上。
  3. Render tree的各个节点计算布局信息,比如box的位置与尺寸。
  4. 利用浏览器的UI层对Render tree进行绘制。
    在明确了页面的呈现过程后,有个问题就呼之欲出了,那就是:

什么因素会影响页面的渲染速度

事实上,paint就是一个耗时的过程,而第三点中的layout是一个更为耗时的过程。
layout发生在页面渲染前,用来计算文档中DOM元素的位置和大小。第一次加载了html文档后就会进行layout操作,之后的js执行和css样式的改变也会触发浏览器去执行layout。甚至一次layout会牵涉到整个文档布局的重新计算。但是layout又无法避免,所以我们需要尽量少的去让游览器做layout
一般情况下,浏览器的layoutlazy的,也就是说:在js脚本执行时,是不会去更新DOM的,任何对DOM的修改都会被暂存在一个队列中,在当前js的执行上下文完成执行后,会根据这个队列中的修改进行一次layout。然而有时候我们希望在js代码中立刻获取最新的DOM节点信息,这种情况下浏览器就不得不提前执行layout,这是导致DOM性能问题的主因。
一般来说,如下的操作会触发浏览器执行layout

  1. 通过js获取需要计算的DOM属性
  2. 添加或删除DOM元素
  3. resize浏览器窗口大小
  4. 改变字体
  5. css伪类的激活,比如:hover
  6. 通过js修改DOM元素样式且该样式涉及到尺寸的改变