js repaint 重绘 reflow 渲染

我们先看一下浏览器解析的工作流程


从图上可以看出,浏览器的工作流程可分为四步:

1、解析HTML构建DOM树:渲染引擎开始解析HTML文档,转换树中的HTML标签或者js生生的标签到DOM节点,它被称为内容树。即图中第一个黄色椭圆

2、构建渲染树:解析css(包括外部css文件和样式元素以及js生成的样式),根据css选择器计算出节点的样式,创建另一个数,渲染树。即图中第二个黄色椭圆

3、布局渲染树:从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点所应该在屏幕上出现的青雀坐标。即图中第三个黄色椭圆

4、绘制渲染树:遍历渲染树,每个节点将使用UI后端层来绘制。即图中第四个黄色椭圆。

可以看出, reflow 和repaint分别对应步骤中的第三步和第四步

reflow 重写

1、什么是reflow

对于DOM结构中的各个元素都有自己的盒子模型,这些都需要浏览器根据各种样式(浏览器的、开发人员定义的等)来计算并根据计算结果将元素放到它该出现的位置,这个过程称为 reflow

2、什么情况下会导致reflow

(1)DOM元素的添加、修改(内容)、删除( Reflow + Repaint);

(2)当你移动 DOM 的位置,或是搞个动画的时候;

(3)当你 Resize 窗口的时候(移动端没有这个问题),或是滚动的时候。

(4)读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、 scrollTop/Left/Width/Height、clientTop/Left/Width/Height、 getComputedStyle()、currentStyle(in IE))

注:display:none 会发生reflow ,而,visibility:hidden 只会触发repaint ,因为它没有发现位置的变化。

3、为什么reflow不可取

DOM Tree里每一个结点都会有reflow方法,一个结点的reflow可能会导致其子结点,甚至父级结点以及同级结点的reflow,同时他会触发repaint,并且reflow的开销非常昂贵。在一些高性能的电脑上或许没什么,但是如果reflow发生在低性能比如手机上,那么这个过程非常痛苦和耗电的。

“A reflow is even more critical to performance because it involves changes that affect the layout of a portion of the page (or the whole page). Reflow of an element causes the subsequent reflow of all child and ancestor elements as well as any elements following it in the DOM. Reflows are very expensive in terms of performance, and is one of the main causes of slow DOM scripts, especially on devices with low processing power, such as phones. In many cases, they are equivalent to laying out the entire page again.”

repaint 重绘

1、什么是repaint

当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上,这个过程称为repaint

2、什么情况下会导致repaint

“A repaint occurs when changes are made to an elements skin that changes visibility, but do not affect its layout.” --重绘发生在元素的可见的外观被改变,但并没有影响到布局的时候。比如,仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)

3、为什么repaint 不可取

repaint的开销是昂贵的,因为浏览器必须验证DOM Tree中所有结点的可见性。

“repaint is expensive because the browser must verify the visibility of all other nodes in the DOM tree.”

////

怎么样优化

Reflow是不可避免的,只能将Reflow对性能的影响减到最小

(1)DOM离线后修改。如:

    a)先把DOM给display:none(有一次reflow),然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来。

    b)如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document

        var fragment = document.createDocumentFragment();

        fragment.appendChild(document.createTextNode('test 111'));

        fragment.appendChild(document.createElement('br'));

        fragment.appendChild(document.createTextNode('test 222'));

        document.body.appendChild(fragment);

    c)clone一个DOM节点(使用cloneNode()方法)到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。克隆一个结点cloneNode(true)深度克隆(将deep设置成了true),即同时会克隆该结点的所有子结点。cloneNode(false)浅克隆(将deep设置成false),即仅仅克隆当前结点。如何将结点克隆到内存?如何和在线的交换?(暂时不会做)

(2)集中修改样式

    a)尽可能少的修改style上的属性

    b)尽量通过修改className来修改样式。

    c)通过cssText属性来设置样式。因为 element.style.width=”80px”;  //reflow  。调用一次就会产生一次reflow 调用越多产生越多。所以,element.style.cssText=”width:80px;height:80px;border:solid 1px red;”; //reflow  。 只产生一次reflow。

(3)缓存layout的值。var left = ele.offsetLeft; 多次使用left也就产生一次reflow。

(4)设置元素的position的属性为absolute 或者fixed 。元素脱离标准流也就从DOM Tree中脱离出来,在需要reflow的时候只需要reflow自身以及下级元素。

(5)尽量不要使用table布局。table元素一旦触发reflow就会导致table里所有的其它元素 reflow。在适合用table的场合,可以设置table-layout为auto或fixed,这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围

(6)避免使用expression,因为expression对浏览器资源要求比较高。它会每次调用都会重新计算一遍(包括加载页面)

在CSS中使用expression,用来把CSS属性和Javascript表达式关联起来,这里的CSS属性可以是元素固有的属性,也可以是自定义属性。就是说CSS属性后面可以是一段Javascript表达式,CSS属性的值等于Javascript表达式计算的结果。 在表达式中可以直接引用元素自身的属性和方法,也可以使用其他浏览器对象。

#container { width: expression((documentElement.clientWidth < 725) ? "725px" : "auto" ); }相当于:min-width: 725px

/-----------------------------实际应用---------------------------/

页面滚动时,网站导航条固定悬浮在页面顶部,同时固定悬浮条的出现和消失都是transition:ease-out动画效果。

1、具体实现


<一>页面HTML代码

(1)当页面滚动一定距离(具体值自己根据需求设定)的时候隐藏。

下面是对应的css
注!如果没有margin-top便没有动画ease-out的效果

(2)页面继续滚动到一定距离(具体值自己根据需求设定)的时候显示


js动态添加的class ,下面是具体样式
注!z-index为了防止被页面中其他脱离文档流的元素覆盖。

有了以上的代码,页面的效果也就出来了,但是有点小bug。导航条元素原本有一定高度,因为使用fixed的定位之后,元素就会脱离文档流,原本在文档中的位置也就会消失,页面就会整体上移导航条高度的距离,会产生一次reflow,这次的reflow不可避免,因为是效果的需要。页面整体的上移就会是页面又一点抖的bug,如果文档的高度恰巧在浏览器窗口的高度与hidden的值之和浏览器窗口的高度与hidden的值之和之间,而文档的高度又小于浏览器窗口的高度与一次scroll的高度(100px或者114px,不同内核的浏览器有些不一样),这段距离就是临界区域,鼠标滚动一下页面就会上下的闪一下,效果感觉就不会很好。

2、解决办法:当元素position:fixed脱离文档流的时候,原来导航条高度不让它消失。

(1)给body添加padding-top:导航条高度

(2)给导航条元素外再加一个父级div并设置height:导航条高度,当导航条脱离的时候仍有其父元素占位。

(3)给导航条的下一个元素(弟弟元素)添加margin-top:导航条高度。如果导航条所在页面是模板,有好多的页面都在引用,那么这种方法不可取,因为会有好多页面都会引用导航条所在的模板页面,这就导致了导航条的下一个元素不唯一,总不能所有的页面中的导航条的下一个元素都用js添加样式。

(4)初始状态给body添加一个padding-top,并且初始状态就将导航条用position:absolute脱离文档流

第一种方法和第三种方法的原理是一样的,都是用js操作css动态给DOM结点添加样式,会产生一次reflow。而第二种和第四种方式就不会产生reflow。那么这个效果的实现至少就会减少一次的reflow。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容