前端: 浏览器的渲染过程、回流、重绘

一、浏览器的渲染过程

1.根据HTML生成DOM树

浏览器在接收到服务器发来的HTML文件是字节形式的,首先要将字节形式的HTML组建成字符串,然后将字符串
转换成token,再将token组装成node节点,最后用node节点组成Dom。

所以DOM(Document Object Model) 文档对象模型可以分解成。

D:document 由元素节点组成的文档 层级是文档包含节点节点包含元素。

O: object 将Dom转化成Dom对象。

M:model 是dom的主要骨架,将页面的标签按照层级从上到下加载每一个节点
image

2.根据Css生成Css树

按照Dom树的基本骨架添加样式,Css样式可以继承父节点的样式,如果自己定义了同样的属性就会将父类的覆盖掉
例如:

点击查看代码
  <body style="font-size:16px;">
  		<div>
		     <p style="font-weight: bold;">
                    pStyle
               <span style="color:red">spanStyle</span>
             </p>
		</div>

  </body>


image

3.根据Dom树、Css树生成Render树

render树是以Dom树为骨架,以Css树为装饰搭建组合成的一个渲染树,然后结合渲染规则和布局进行渲染页面
image

这里要强调一下js代码需要注意的一点: 遇到js代码会先运行js代码,直到js代码块执行完再继续渲染页面,
因为js代码一般都是操作Dom元素的所以js一般放在页面的底部

二、浏览器的重绘与回流(重排)

1.重绘与回流

重绘:当元素属性发生改变且不影响布局时(背景颜色、透明度、字体样式等),产生重绘相当于不刷新页面,动态更新内容。

回流(重排):当元素属性发生改变且影响布局时(宽度、高度、内外边距等),产生回流,相当于 刷新页面。

重绘一般发生的比较频繁,因为页面很小的一个改动也会引起重绘,值得注意的是重绘消耗的性能要比回流(重排)要小,发生重绘不一定发生回流,但是发生回流一定会发生重绘

2.如何减少重绘与回流

①.使用 transform 替代 top

在2d或3d场景移动元素的时候会用到 transform 和top top是延时三秒后执行移动 所以transform性能也会比top好一些

②.使用 opacity:0、visibility:hidden 替换 display: none

opacity:0和visibility:hidden都是将元素隐藏只会引起重绘   display: none也是隐藏但是相当于将该部分删除 会造成回流(重排),
如图是三种属性对页面以及子元素的影响。

image

③.不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局

table是用来展示数据的组件,不能用来布局,如果使用了table布局其中的元素长度发生变化或者行高发生变化都会造成table
单元格大小尺寸的变化这时就会发生回流,数据是多变的会很频繁的发生回流进而很大的消耗了浏览器的性能

④.动画实现的速度的选择、动画速度越快、回流次数越多、也可以选择使用requestAnimationFrame

动画实现的速度与显示器刷新的频率是决定动画渲染的流畅度的,如果动画渲染过快,显示器跟不上动画渲染的速度就会造成重绘或者回流,
requestAnimationFrame是实现动画常用的方法,效果与setTimeOut、setInterval类似但是有本质上的不同

1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随
浏览器的刷新频率,一般来说,这个频率为每秒60帧。

2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

⑤.CSS 选择符从右往左匹配查找,避免节点层级过多
例如:设置样式 .div-content .div-style .span{font-size:10px;}
image
Css的匹配规则就是从右往左

方案一:从左向右的匹配规则

从.div-content开始遍历子节点.div-style和子节点div,当遍历右侧的div分支时,遍历到a标签发现没有满足条件的,
就回溯到ul继续下一个分支的遍历,直到便利完ul下所有的分支,如果右侧的分支很多,则这样的遍历和回溯就会耗费很多性能

方案二:从右向左的匹配规则

先找到所有的最右侧节点span,然后逐次向上寻找.div-style节点和.div-content节点,直到找到根元素html

⑥.将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。比如对于 video 标签来说,浏览器会自动将该节点变为图层.

⑦.减少对Dom的操作尽量进行一次性操作,减少回流,例如Vue的虚拟Dom或者将需要修改的节点克隆在修改之后替换到真正的Dom

⑧.将需要操作的Dom进行离线处理,即给需要离线的元素设置属性display:none,离线后对离线Dom进行操作,操作完之后将disply属性设置成可见,这样就可以只进行一次重绘与回流。

posted @ 2022-10-08 17:13  leayun  阅读(237)  评论(0编辑  收藏  举报