浏览器的渲染页面过程和重排、重绘

摘要:
渲染页面的过程:1.解析html源码,创建dom树。产生重排或重绘的操作:增加或删除DOM节点设置display:none;或者visibility:hidden移动页面中的元素增删或者修改样式计算offsetWidth和offsetHeight用户改变窗口大小,滚动页面等浏览器的处理方案:因为渲染树的改变导致的重绘或重排操作都可能代价很高,浏览器会对这个改动做很多优化。通过display:none来隐藏节点,做大量的修改,然后显示节点,总共只会有两次重排。

渲染页面的过程:

1.解析html源码,创建dom树。每个标签都是一个节点。

2.解析css

3.构建dom树,并且计算出样式(padding、margin等),然后构建 渲染树。对于渲染树和dom树的不同是:dom树的每一个标签都是一个节点,但是渲染树会忽略掉不需要渲染的元素,例如head、display:none的元素。渲染树中的每一个节点都存储有对应的css属性。

4.渲染树创建好后,浏览器就可以根据渲染树直接把页面绘制到屏幕上。

重排和重绘:

重排:就是渲染树的一部分必须要更新 并且节点的尺寸发生了变化。这就会触发重排操作(相当于渲染树需要重新计算.....)。

重绘:部分节点需要更新,但是没有改变他的集合形状,比如改变了背景颜色,这就会触发重绘。

产生重排或重绘的操作:

(1)增加或删除DOM节点
(2)设置 display: none;(重排并重绘) 或者 visibility: hidden(只有重排)
(3)移动页面中的元素

(4)增删或者修改样式

(5)计算offsetWidth和offsetHeight

(6)用户 改变窗口大小,滚动页面等

浏览器的处理方案:

因为渲染树的改变导致的重绘或重排操作都可能代价很高,浏览器会对这个改动做很多优化。

一个策略就是不要立即做操作,而是批量进行。比如把你的脚本对DOM的修改放入一个队列,在队列所有操作结束后只需要进行一次绘制即可。

但是有的时候脚本可能会导致浏览器的批量优化无法进行,可能在清空队列之前就需要重新绘制(绘制意思是重绘或者重排)页面。比如你通过脚本获取这些样式:

offsetTop,offsetLeft,offsetWidth,offsetHeight
scrollTop/Left/Width/Height
clientTop/Left/Width/Height
getComputedStyle(), orcurrentStylein IE

因为浏览器必须给你最新的值,所以当你进行这些取值操作的时候会立刻触发一次页面的绘制。这样本来可以批量修改样式然后一次性绘制的方法就无法使用了。

最后来说以下解决办法:

1.不要一个一个地单独修改属性,最好通过一个classname来定义这些修改

2.把对节点的大量修改操作放在页面之外,用 documentFragment来做修改,clone 节点,在clone之后的节点中做修改,然后直接替换掉以前的节点。
通过 display: none 来隐藏节点(直接导致一次重排和重绘),做大量的修改,然后显示节点(又一次重排和重绘),总共只会有两次重排。

3.不要频繁获取计算后的样式。如果你需要使用计算后的样式,最好暂存起来而不是直接从DOM上读取。

4.减少table布局(话说,很少有用table布局的了吧 现在,都过时了....)

5.避免css表达式,(因为每当文档重新加载或者部分文档重新加载的时候,CSS表达式都会重新计算一次,因此其性能会受到非常大的影响。)

6.总的来说,总是考虑到渲染树得存在,考虑到你的一次修改会导致多大的绘制操作。(比如绝对定位元素的动画就不会影响其他大部分元素)。

免责声明:文章转载自《浏览器的渲染页面过程和重排、重绘》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【腾讯Bugly干货分享】Android 插件技术实战总结后台发送请求,HttpClient的post,get各种请求,带header的请求下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

吐槽下若依(RuoYi)系统的权限系统(shiro和spring-security)

spring-security以RuoYi-Vue为例,当前版本是3.1.0。然后是系统中很多地方用LoginUserloginUser=tokenService.getLoginUser来获取当前用户数据,这个需要再解析token,然后从redis缓存中读取的数据,不明白为什么不直接从SecurityUtils.getLoginUser()中获取,明明已经...

java报表实现excel一样冻结表头的功能

增加了几个新的指标,后台sql改了,拿过来只须在一个dao类中修改就足够了,可恨的是客户又提出来改报表表样,加个类似excel冻结表头的功能。...

微信小游戏流量主广告接入指南!

游戏通过审核发布上线,累计注册用户达到1000后,可以在管理后台开启流量主功能。广告接入广告类型有三种:激励式视频、插屏和BannerBanner广告接入需要注意:1.广告要显示全,不能放在屏幕外。我的游戏被以上原因拒绝了两次。我的banner广告是放在底部正中间,取最小宽度200。也就是尽量的小,不影响游戏操作。激励视频按钮一定要有视频广告相关的提示!...

c# Socket心跳试验,自定义发送包 和 使用KeepAlive

我记录了我心跳的位置,但WireShark无法检测到正在发送的消息,主要是因为发送的数据大小为0。如果网络电缆被拔掉,下次检测到心跳时就会报告错误。虽然这种方法可以检测套接字是否断开,但它不是很好,响应也不及时。当使用KeepAlive时,WireShark通常会检测到它不停地向Socket服务器发送消息,即心跳检测。图:通过三次握手(前三次握手)建立连接后...

PowerQuery清理非文件名字符(清除指定列表中的所有字符)

在左侧导航窗格的空白区域右击,依次找到空白查询项接下来的思路是:遍历列表SearchList中的所有项,依次清理Data表中所有想要处理的列。第三个参数是一个函数:它告诉List.Accumulate函数,在每一次使用SearchList中某一项操作Data表时,其操作的方式是如何的。...

如何设置Navicat的显示字体与字体大小?

方法/步骤打开Navicat点击菜单,再选择在界面,点击下的设置网格字体和大小设置编辑器字体和大小设置命令列界面字体和大小设置ER图表字体和大小,最后点击END...