页面的重绘与回流,以及如何优化

一个人想着一个人 提交于 2019-12-17 12:29:50

页面的重绘与回流,以及如何优化

浏览器对页面的呈现流程

页面呈现流程

浏览器把取到的HTML代码解析成1个DOM树

HTML中的每个tag都是DOM中的1个节点

根节点是document对象

DOM树里包含了所有HTML标签

包括display:none;隐藏(因为DOM tree无法识别样式),还有用JS动态添加的元素等

浏览器把所有样式解析成样式结构体,解析过程中会去掉浏览器不能识别的样式(例如:IE会去掉-moz开头的样式)

DOM tree和样式结构体组合构建render tree

render tree类似于DOM tree

render tree能识别样式,render tree中的每个节点都有自己的style

render tree不包含隐藏的节点(例如:display:none;的节点和head节点)

页面加载时,不会呈现且不会影响呈现的节点不会包含到render tree中

visibility:hidden;会影响布局(layout),会占有空间

浏览器根据构建好的render tree来绘制页面

回流与重绘

1、概述

当render tree中的一部分(或全部),因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就是回流(reflow)

每个页面至少回流一次,即页面首次加载

回流时,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树

回流完成后,浏览器会重新绘制受影响的部分,是重绘过程

当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而不影响布局(例如:background-color),则称为重绘(repaints)

回流必将引起重绘,重绘不一定引起回流

回流比重绘的代价更高

2、回流何时发生

当页面布局和几何属性改变时就需要回流

添加或者删除可见的DOM元素

元素改变位置和计算offsetWidth和offsetHeight属性

元素尺寸改变–边距、填充、边框和宽高

内容改变(例如:文本改变、图片大小改变而引起的计算值宽度和高度改变,input框中输入文字)

页面渲染初始化

浏览器窗口尺寸改变–resize事件发生时

增加或移出样式表

操作class属性

改变字体

激活伪类(例如:hover)

回流的花销跟render tree有多少节点需要重绘有关系(比如在body最前面插入1个元素,会导致整个render tree回流,如果在body后面插入1个元素,则不会影响前面元素的回流)

let box = document.getElementById(“box”).style;

box.padding = “2px”; // 回流+重绘

box.border = “1px solid red”; // 再一次 回流+重绘

box.color = “blue”; // 重绘

box.backgroundColor = “#ccc”; // 重绘

box.fontSize = “14px”; // 回流+重绘

document.getElementById(“box”).appendChild(document.createTextNode(‘abc!’));

3、浏览器优化

上面的代码在Chrome浏览器中实际上是看不出差别的,因为很多浏览器都会优化这些操作。浏览器会维护1个队列,把所有引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定时间间隔,浏览器就会flush队列,进行一个批处理。这样让多次回流和重绘变成一次回流重绘。

某些情况下浏览器优化会不起作用,当浏览器请求一些style信息的时候,会让浏览器flush队列,比如:

offsetTop/offsetLeft/offsetWidth/offsetHeight

scrollTop/Left/Width/Height

clientTop/Left/Width/Height

width,height

请求了getComputedStyle(), 或者 IE的 currentStyle

请求上面一些属性的时候,浏览器为了给出精确值,需要flush队列,因为队列中可能会影响到这些值得操作,所以浏览器会强行刷新渲染队列。

如何减少回流、重绘

减少回流、重绘就是需要减少对render tree的操作,并减少对一些style信息的请求,合理利用浏览器优化策略。有一下方法:

直接改变className,如果动态改变样式,使用cssText(减少设置多项内联样式)

// bad

elem.style.left = x + “px”;

elem.style.top = y + “px”;

// good

elem.style.cssText += ";left: " + x + "px;top: " + y + “px;”;

让要操作的元素进行“离线处理”,处理完后一起更新

当用DocumentFragment进行缓存操作,引发一次回流和重绘

使用display:none技术,只引发两次回流和重绘

使用cloneNode(true or false)和replaceChild技术,引发一次回流和重绘

不要经常访问会引起浏览器flush队列的属性,确实要访问,利用缓存

// bad

for (var i = 0; i < len; i++) {

el.style.left = el.offsetLeft + x + “px”;

el.style.top = el.offsetTop + y + “px”;

}

// good

var x = el.offsetLeft,

y = el.offsetTop;

for (var i = 0; i < len; i++) {

x += 10;

y += 10;

el.style = x + “px”;

el.style = y + “px”;

}

让元素脱离动画流,减少render tree的规模,动画效果应用position属性的fixed值或absolute值

尽可能在DOM树的最末端改变class,尽可能在DOM树的里面改变class(可以限制回流的范围)

牺牲平滑度换区速度

避免使用table布局

IE中避免使用JavaScript表达式

浏览器对页面的呈现流程
页面呈现流程浏览器把取到的HTML代码解析成1个DOM树HTML中的每个tag都是DOM中的1个节点根节点是document对象DOM树里包含了所有HTML标签包括display:none;隐藏(因为DOM tree无法识别样式),还有用JS动态添加的元素等浏览器把所有样式解析成样式结构体,解析过程中会去掉浏览器不能识别的样式(例如:IE会去掉-moz开头的样式)DOM tree和样式结构体组合构建render treerender tree类似于DOM treerender tree能识别样式,render tree中的每个节点都有自己的stylerender tree不包含隐藏的节点(例如:display:none;的节点和head节点)页面加载时,不会呈现且不会影响呈现的节点不会包含到render tree中visibility:hidden;会影响布局(layout),会占有空间浏览器根据构建好的render tree来绘制页面回流与重绘1、概述当render tree中的一部分(或全部),因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就是回流(reflow)每个页面至少回流一次,即页面首次加载回流时,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树回流完成后,浏览器会重新绘制受影响的部分,是重绘过程当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而不影响布局(例如:background-color),则称为重绘(repaints)回流必将引起重绘,重绘不一定引起回流回流比重绘的代价更高2、回流何时发生当页面布局和几何属性改变时就需要回流
添加或者删除可见的DOM元素元素改变位置和计算offsetWidth和offsetHeight属性元素尺寸改变–边距、填充、边框和宽高内容改变(例如:文本改变、图片大小改变而引起的计算值宽度和高度改变,input框中输入文字)页面渲染初始化浏览器窗口尺寸改变–resize事件发生时增加或移出样式表操作class属性改变字体激活伪类(例如:hover)回流的花销跟render tree有多少节点需要重绘有关系(比如在body最前面插入1个元素,会导致整个render tree回流,如果在body后面插入1个元素,则不会影响前面元素的回流)
let box = document.getElementById(“box”).style; box.padding = “2px”; // 回流+重绘 box.border = “1px solid red”; // 再一次 回流+重绘 box.color = “blue”; // 重绘 box.backgroundColor = “#ccc”; // 重绘 box.fontSize = “14px”; // 回流+重绘 document.getElementById(“box”).appendChild(document.createTextNode(‘abc!’));3、浏览器优化上面的代码在Chrome浏览器中实际上是看不出差别的,因为很多浏览器都会优化这些操作。浏览器会维护1个队列,把所有引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定时间间隔,浏览器就会flush队列,进行一个批处理。这样让多次回流和重绘变成一次回流重绘。某些情况下浏览器优化会不起作用,当浏览器请求一些style信息的时候,会让浏览器flush队列,比如:
offsetTop/offsetLeft/offsetWidth/offsetHeightscrollTop/Left/Width/HeightclientTop/Left/Width/Heightwidth,height请求了getComputedStyle(), 或者 IE的 currentStyle请求上面一些属性的时候,浏览器为了给出精确值,需要flush队列,因为队列中可能会影响到这些值得操作,所以浏览器会强行刷新渲染队列。
如何减少回流、重绘减少回流、重绘就是需要减少对render tree的操作,并减少对一些style信息的请求,合理利用浏览器优化策略。有一下方法:
直接改变className,如果动态改变样式,使用cssText(减少设置多项内联样式)// badelem.style.left = x + “px”;elem.style.top = y + “px”;// goodelem.style.cssText += ";left: " + x + "px;top: " + y + “px;”;让要操作的元素进行“离线处理”,处理完后一起更新当用DocumentFragment进行缓存操作,引发一次回流和重绘使用display:none技术,只引发两次回流和重绘使用cloneNode(true or false)和replaceChild技术,引发一次回流和重绘不要经常访问会引起浏览器flush队列的属性,确实要访问,利用缓存// badfor (var i = 0; i < len; i++) { el.style.left = el.offsetLeft + x + “px”; el.style.top = el.offsetTop + y + “px”;}// goodvar x = el.offsetLeft, y = el.offsetTop;for (var i = 0; i < len; i++) { x += 10; y += 10; el.style = x + “px”; el.style = y + “px”;}让元素脱离动画流,减少render tree的规模,动画效果应用position属性的fixed值或absolute值尽可能在DOM树的最末端改变class,尽可能在DOM树的里面改变class(可以限制回流的范围)牺牲平滑度换区速度避免使用table布局IE中避免使用JavaScript表达式--------------------- 作者:IT修真院 来源:CSDN 原文:https://blog.csdn.net/jnshu_it/article/details/77367282 版权声明:本文为博主原创文章,转载请附上博文链接!

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!