hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

从浏览器衬着道理,浅谈回流重绘与机能优化

2019-11-18杂谈搜奇网21°c
A+ A-

目次

  • 媒介
  • 浏览器的衬着引擎
    • 衬着流程
    • 衬着树与衬着对象
  • 回流
    • 全局规划和增量规划
    • "回流"照样"重排"?
  • 重绘
  • 什么时刻触发回流和重绘
  • 衬着机能优化
    • 兼并屡次规划操纵
    • 削减或防止强迫同步规划
    • 运用 transformopacity 来完成动画
    • 简化绘制的庞杂度、减小绘制地区
    • 让庞杂的规划“离线”
    • 其他
  • 参考文献

媒介

“回流(重排)”和“重绘”基础上算是前端的高频词之一,你能够在各个文章及口试题中见到,我们在议论这个词的时刻,实在议论的是浏览器的衬着流程。
所以在议论“回流重绘”之前,我们还须要控制一些学问;在它当中,我们还须要更深切一点;在这以后,我们还要晓得怎样去把理论连系到项目实践中去。

经由历程这篇文章,你能够进修到的学问:
1、追根究底,“回流”和“重绘”这个词是怎样引出的,在相识这两个词之前我们还须要相识什么
2、浏览器的衬着流程,“回流”和“重绘”的道理
3、优化浏览器衬着机能,削减“回流”和“重绘”,着手将这些优化运用到现实开辟中

浏览器的衬着引擎

浏览器的重要组件有:用户界面、浏览器引擎、衬着引擎、收集、用户界面后端、JavaScript诠释器、数据存储。

浏览器的重要功能就是向服务器发出要求,在浏览器窗口中展现您挑选的收集资源。浏览器在剖析HTML文档,将网页内容展现到浏览器上的流程,实在就是衬着引擎完成的。

衬着流程

我们在这里议论Gecko和Webkit这两种衬着引擎,个中Firefox 运用的是 Gecko,这是 Mozilla 公司“克己”的显现引擎。而 Safari 和 Chrome 浏览器运用的都是 WebKit。

WebKit 衬着引擎的主流程:

Mozilla 的 Gecko衬着引擎的主流程:

从图 3 和图 4 能够看出,虽然 WebKit 和 Gecko 运用的术语略有差别,但团体的衬着流程是基础雷同的,这里我们参照Webkit引擎来概略一下:

  1. 剖析HTML Source,生成DOM树
  2. 剖析CSS,生成CSSOM树
  3. 将DOM树和CSSOM树连系,去除不可见元素,生成衬着树(Render Tree)
  4. Layout(规划):依据生成的衬着树,举行规划(Layout),获得节点的多少信息(位置,大小)
  5. Painting(重绘):依据衬着树以及回流获得的多少信息,将 Render Tree 的每一个像素衬着到屏幕上

衬着树与衬着对象

衬着树(render tree)是由可视化元素根据其显现递次而构成的树,也是文档的可视化示意。它的作用是让您根据准确的递次绘制内容。

生成衬着树

为了构建衬着树,浏览器重要完成了以下事情:

  1. 从DOM树的根节点最先遍历每一个可见节点。
  • 某些节点不会被衬着输出,比方scriptlinkmeta等标签节点
  • 经由历程css隐蔽的节点会被疏忽,比方“display: none”。然则注重,visibility: hidden是会被衬着的(衬着成一个空框),由于它仍占有规划空间
  1. 关于每一个可见的节点,找到CSSOM树中对应的划定规矩,并运用它们。
  2. 依据每一个可见节点以及其对应的款式,组合生成衬着树。

衬着对象

Firefox 将衬着树中的元素称为“框架”。WebKit 运用的术语是衬着器(renderer)或衬着对象(render object)。 

每一个衬着对象都代表了一个矩形地区,平常对应相干节点的css框,包含宽度、高度和位置等多少信息。框的范例受“display”款式属性影响,依据差别的 display 属性,运用差别的衬着对象(如 RenderInlineRenderBlockRenderListItem 等对象)。

WebKits RenderObject 类是一切衬着对象的基类,其定义以下:

class RenderObject{
  virtual void layout();
  virtual void paint(PaintInfo);
  virtual void rect repaintRect();
  Node* node;  //the DOM node
  RenderStyle* style;  // the computed style
  RenderLayer* containgLayer; //the containing z-index layer}

我们能够看到,每一个衬着对象都有 layoutpaint要领,离别对应了回流和重绘的要领。

回流

衬着对象在建立完成并增加到衬着树时,是将DOM节点和它对应的款式连系起来,并不包含位置和大小信息。

我们还须要经由历程 Layout 规划阶段,来盘算它们在装备视口(viewport)内的确实位置和大小,盘算这些值的历程称为回流规划重排

HTML 采纳基于流的规划模子,从根衬着对象(即<html>)最先,递归遍历部份或一切的框架条理构造,为每一个须要盘算的衬着对象盘算多少信息,大多数状况下只需一次遍历就可以盘算出多少信息。然则也有破例,比方<table>的盘算就须要不止一次的遍历。

全局规划和增量规划

全局规划指触发了全部render tree局限的规划,平常是同步触发的,触发缘由能够包含:

  1. 影响一切衬着元素的全局款式变动,比方字体大小变动。
  2. 屏幕大小调解。

增量规划是指对标记为“dirty”的衬着对象举行规划。它平常是异步实行的,浏览器将增量规划的“reflow 敕令”到场行列,而调理顺序会触发这些敕令的批量实行。

然则要求款式信息(比方offsetHeight,
getBoundingClientRect等)的脚本可同步触发增量规划。 

Note: dirty bit
为防止对一切微小变动都举行团体规划,浏览器采纳了一种“dirty bit”的体系。假如某个衬着对象发作了变动,或许将本身及其子代标注为“dirty”,则须要举行规划。

"回流"照样"重排"?

本质上它们是一样的流程,只是在差别浏览器引擎下的“说法”有所差别。

  • Gecko 将视觉格式化元素构成的树称为 "Frame tree" 框架树。每一个元素都是一个框架;
    关于元素的安排,将其称为 "Reflow" 回流

  • WebKit 运用的术语是 "Render Tree" 衬着树,它由"Render Objects"构成。关于元素的安排,WebKit 运用的术语是 "Layout" 规划(或Relayout重排

重绘

在盘算出节点可见性、它们的盘算款式以及多少信息后,我们还须要将衬着树中的每一个节点,转换成屏幕上的现实像素。这一步平常称为“重绘”。

重绘是添补像素的历程。它触及绘出文本、色彩、图象、边框和暗影,基础上包含元素的每一个可视部份。在重绘阶段,体系会遍历衬着树,并挪用衬着对象的“paint”要领,将衬着对象的内容显现在屏幕上。

和规划一样,重绘也分为全局(绘制全部render tree)和增量两种。

绘制递次

绘制的递次实在就是元素进入客栈款式上下文的递次。这些客栈会从后往前绘制,因而如许的递次会影响绘制。块衬着对象的客栈递次以下:
1、背景色彩
2、背景图片
3、边框
4、子代
5、表面

什么时刻触发回流和重绘

触发回流(reflow):

回流这一阶段重如果盘算节点的位置和多少信息,那末当页面规划和多少信息发作变化的时刻,就须要回流.

转变这些属性会触发回流:

  • 盒模子相干的属性: widthheightmargindisplayborder
  • 定位属性及浮动相干的属性: top,position,float
  • 转变节点内部笔墨构造也会触发回流:text-align, overflow, font-size, line-height, vertival-align

以及举行以下流程或操纵:

  • 页面一最先衬着的时刻
  • 增加或删除可见的DOM元素,举行DOM操纵等
  • 内容发作变化,比方文本变化或图片被另一个差别尺寸的图片所替换
  • 浏览器的窗口尺寸变化(由于回流是依据视口的大小来盘算元素的位置和大小的)
  • css伪类激活
  • 举行猎取规划信息的操纵,比方offsetWidthoffsetHeightclientWidthclientHeightwidthheightscrollTopscrollHeight,getComputedStyle, getBoundingClientRect

Note: 详细属性及操纵能够接见这个网站:What forces layout / reflow

触发重绘:

重绘是一个元素表面的转变所触发的浏览器行动,比方转变visibilityoutlinebackground-color等属性,这些属性只是影响元素的表面,作风,而不会影响规划的。

浏览器会依据元素的新属性从新绘制,使元素显现新的表面。重绘不会带来从新规划,并不一定陪伴回流。

Note: 假如想知道变动任何指定 CSS 属性将触发回流照样重绘,请检察 CSS 触发器

我们依据衬着的流程可知,回流一定会触发重绘,而重绘不一定会回流

衬着机能优化

回流和重绘的价值是比较高贵的,衬着机能优化,就是要尽能够削减Layout回流和Paint重绘发作的次数,将回流和重绘的影响局限限定在零丁的图层以内

兼并屡次规划操纵

我们能够兼并屡次对DOM和款式的修正,然后一次处置惩罚掉,以此来最小化回流和重绘操纵,比方:

// bad
const el = document.getElementById('test');
el.style.margin = '5px';
el.style.width = '100px';
el.style.borderRight = '2px';

例子中,有三个款式属性被修正了,每一个都邑影响元素的多少构造,激发回流。(固然,大部份当代浏览器都对其做了优化,只会触发一次。然则假如在旧版的浏览器或许在上面代码实行的时刻,有其他代码接见了规划信息,那末就会致使三次回流)

我们兼并一切的规划操纵,然后一致处置惩罚,比方如许:

// good
const el = document.getElementById('test');
el.style.cssText += 'margin: 5px;width: 100px;border-right: 2px; '

削减或防止强迫同步规划

上面我们提到,接见一些属性(就是offsetWidth那一堆属性)会致使浏览器强迫清空行列,举行强迫同步规划。现实运用中能够只管防止,假如不能防止,也应当削减。

比方我们想批量将一些标签的宽度设为某个box的宽度,我们能够会写成下面如许:

// bad
   for (let i = 0; i < elment.length; i++) {
        elment[i].style.width = box.offsetWidth + 'px';
    }

这段代码看上去题目不大,然则在每次轮回的时刻,都邑去读取box的offsetWidth,致使浏览器每次都邑因强迫同步规划而触发回流,造成了很大的机能题目。

相似这这状况,我们能够把读取到的offsetWidth举行缓存:

// good
const width = box.offsetWidth;
for (let i = 0; i < element.length; i++) {
    element[i].style.width = width + 'px';
}

运用 transformopacity 来完成动画

最好的机能衬着流程,就是直接避开回流和重绘,只运转Composite合成这一操纵。

现在能够有合成器零丁处置惩罚的属性有两个:
transforms 和 opacity

比方我们能够运用translate替代lefttop
运用opacity替代visibility

简化绘制的庞杂度、减小绘制地区

除 transform 或 opacity 属性以外,变动任何属性一直都邑触发绘制。

绘制平常是像素管道中开支最大的部份;应尽能够防止绘制。

经由历程层的提升来削减绘制地区

绘制并不是老是绘制到内存中的单个图象。事实上,在必要时浏览器能够绘制到多个图象或合成器层,各个层能够在相互的上面处置惩罚并合成,以建立终究图象。

建立新层的最好体式格局是运用 will-change CSS 属性。
此要领在 Chrome、Opera 和 Firefox 上有用,而且经由历程 transform 的值将建立一个新的合成器层:

.moving-element { 
    will-change: transform;
}

关于不支持 will-change 但受益于层建立的浏览器,比方 Safari 和 Mobile Safari,须要开启GPU加速来强迫建立一个新层:

.moving-element { 
    transform: translateZ(0);
}

优化或削减动画编排

削减绘制地区往往是编排您的动画和变更,使其不过多堆叠,或想法削减动画编排,防止对页面的某些部份设置动画。

下降绘制的庞杂性

一些css属性的绘制比其他绘制的开支更大。比方,绘制任何触及隐约(比方shadow)的元素所花的时候将比绘制一个border的时候要长。

现实开辟中,我们要肯定能否运用一组开支更小的款式,或许替换体式格局来完成终究效果。

让庞杂的规划“离线”

关于庞杂的动画,或许频仍触发回流的元素,我们
建立一个documentFragmentdiv,在它上面运用一切DOM操纵,末了再把它增加到window.document

也能够在一个display:none的元素上举行操纵,终究把它显现出来。由于display:none上的DOM操纵不会激发回流和重绘。

也能够运用相对定位,让它离开文档流,从而防止激发父元素以及后续元素的频仍回流。

其他

防止运用table规划

我们已在上面说过,<table>的盘算须要不止一次的遍历,table是能够影响之前已进入的DOM元素的显现的元素。纵然一些小的变化和会致使table中一切其他节点回流。

参考文献

浏览器的事情道理:新式收集浏览器幕后揭秘

Google Developers:衬着树构建、规划及绘制

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
从浏览器衬着道理,浅谈回流重绘与机能优化

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/281976.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>