You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// bad
function resizeAllParagraphsToMatchBlockWidth() {
for (var i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = box.offsetWidth + 'px';
}
}
// better
var width = box.offsetWidth;
function resizeAllParagraphsToMatchBlockWidth() {
for (var i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = width + 'px';
}
}
3.4、 设置具有动画效果的DOM元素为固定定位
使用绝对定位使得该元素在渲染树中成为 body 下的一个直接子节点,因此当它进行动画时,它不会影响太多其他节点。
1、浏览器渲染原理
在讲DOM操作的最佳性能实践之前,先介绍下浏览器的基本渲染原理。浏览器渲染展示网页的主流程大致可以用下图表示:
(图:WebKit 主流程)
分为以下四个步骤:
解析HTML(HTML Parser)
构建DOM树(DOM Tree)
渲染树构建(Render Tree)
绘制渲染树(Painting)
需要着重指出的是,这是一个渐进的过程。为达到更好的用户体验,浏览器会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕之后,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其余内容的同时,浏览器会将部分内容解析并显示出来。
2、Repaints and reflows
Repaint:可以理解为重绘或重画,当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,例如改变背景颜色 。则就叫称为重绘。
Reflows:可以理解为回流、布局或者重排,当渲染树(render Tree)中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow),也就是重新布局(relayout)。
回流或者重绘何时触发?
改变用于构建渲染树的任何内容都可能导致重绘或回流,例如:
1、添加,删除,更新DOM节点
2、用display: none(回流和重绘)或者visibility: hidden隐藏节点(只有重绘,因为没有几何更改)
3、添加样式表,调整样式属性
4、调整窗口大小,更改字体大小
5、页面初始化的渲染
6、移动DOM元素
。。。
我们来看几个例子:
3、DOM操作最佳实践
DOM操作带来的页面 Repaints 和 Reflows 是不可避免的,但可以遵循一些最佳实践来最大限度地减少Repaints 和 Reflows。如下是一些具体的实践方法:
3.1、合并多次的DOM操作
以上所有这些基本上都是请求有关节点的样式信息,浏览器必须提供最新的值。 为了做到这一点,它需要应用所有计划的更改,刷新队列,强行回流。所以在有大批量DOM操作时,应避免获取DOM元素的布局信息,使得浏览器针对大批量DOM操作的优化不被破坏。如果需要这些布局信息,最好是在DOM操作之前就去获取。
3.2、让DOM元素脱离渲染树(render Tree)后修改
(1)使用文档片段
DocumentFragments 是DOM节点。它们不是主DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。在DOM树中,文档片段被其所有的孩子所代替。因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(Reflow)。当然,最后一步把文档片段附加到页面的这一步操作还是会造成回流(Reflow)。
(2)通过设置DOM元素的display样式为none来隐藏元素
原理是先隐藏元素,然后基于元素做DOM操作,经过大量的DOM操作后才把元素显示出来。
(3)克隆DOM元素到内存中
这种方式是把页面上的DOM元素克隆一份到内存中,然后再在内存中操作克隆的元素,操作完成后使用此克隆元素替换页面中原来的DOM元素。
3.3、使用局部变量缓存样式信息
获取DOM的样式信息会有性能的损耗,所以如果存在循环调用,最佳的做法是尽量把这些值缓存在局部变量中。
3.4、 设置具有动画效果的DOM元素为固定定位
使用绝对定位使得该元素在渲染树中成为 body 下的一个直接子节点,因此当它进行动画时,它不会影响太多其他节点。
4、具体例子
4.1、浏览器的批处理及回流
以下会通过一个具体例子来说明,链接地址如下:reflow。
第一次点击的代码如下:
第二次点击的代码如下:
以下我们将通过谷歌工具来查看这两次操作有什么异同。
4.1.1、首先用谷歌浏览器打开如上的链接。按下F12,切换到Performance选项
结果如下图:
4.1.2、按下ctrl + E(或者点击小圆点)开始录制,点击 body 区域,待文字变成绿色后点击“stop”停止录制
结果如下图:
4.1.3、选中上图中蓝色(js堆)突然升高的部分,表示刚才点击body的过程,滚动鼠标放大主线程
结果如下图,注意箭头指的地方:
4.1.4、点击圆点旁边的clear按钮清空,重复上述的操作,直到文字变蓝色停止:
结果如下图,注意箭头指的地方:
4.2、频繁回流造成的影响
谷歌文档给的例子,链接地址如下:animation。
优化前的代码:
优化后的代码:
The text was updated successfully, but these errors were encountered: