一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情
前言
在学习回流和重绘的知识点之前,我们应该了解一下浏览器渲染过程:
- 浏览器发送请求下载了所有的
HTML资源,然后解析HTML, 生成DOM树,解析CSS,生成CSSOM树。 - 将
DOM树和CSSOM树结合,生成 渲染树(Render Tree) 。 - 根据生成的渲染树,进行 回流(Layout) ,得到节点的几何信息(位置,大小)。
- 根据 渲染树 以及 回流 得到的几何信息,重绘(Painting) 得到节点的绝对像素。
- 将像素发送给GPU,展示(Dsiplay) 在页面上 。
其实渲染的过程有点类似于 绘画 一样:
- 构图 — 规划 整体的结构(Render Tree)
- 找出结构线 — 确定每块区域的 位置、大小(Layout)
- 填充内容 — 得到节点的绝对像素 重绘(Painting)
- 深入刻画 — 合并合成层、将像素发送给GPU,展示在页面上等操作 展示(Dsiplay)
关于对绘画的抽象仅代表我个人,我对于浏览器渲染和绘画的理解可能还不到位,如果有不对的地方,还请见谅哈😂 ~~
重绘 (repaint)
概念: 当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
重绘全名就是重新绘画,可以理解为 绘画 时在 画布 上重新给某个东西加上一些颜色或者阴影,而且是在不影响
整个画布排版的情况下。
几个触发重绘的例子:
- 修改元素的 color
- 修改元素的 background-color
- 添加阴影效果 box-shaow
- 隐藏或者显示 visibility
回流 (reflow)
概念: 当部分或者全部元素的尺寸、大小、结构发生改变时,会触发浏览器重新渲染部分或者全部页面的过程称为回流。
回流也可以叫作 重排 ,就是重新排版的意思,可以理解为 绘画 时 因为某一块地方修改了 结构 导致要重新画一次。
几个触发重绘的例子:
- input 输入文字
- 修改元素的宽高、内外边距(padding、margin)
- 添加或删除 DOM 元素
- CSS 伪元素触发,例如 hover
- js 中一些常用的 api,例如修改元素的
offsetWidth、offsetHeight等等 - 浏览器尺寸大小发生变化,例如 resize 事件
两者之间的关系
回流比重绘的代价要高,因为回流会导致部分或者全部页面重新渲染。
经典的代表就是 ul li 元素,这是大家机场使用的标签之一,如果我们在多个 li 之间添加或删除 一个或者多个 li ,就会导致他的父元素以及依赖他的元素产生回流,就像 蝴蝶效应 一般。
大家可以通过在 谷歌浏览器 中 F12 开启控制台,在摁 ESC 打开窗口,点击下图中的 Rendering,勾选上 Paint flashing 就可以查看页面中触发回流和重绘的情况。
如何减少和优化
我们知道了回流和重绘对浏览器渲染造成了一定的性能影响,那我们应该怎么样减少回流和重绘呢?
CSS 方面:
- 避免使用
table布局 - 避免设置多层内联样式
dispaly:none隐藏元素,应用修改,重新显示- 让元素脱离文档流,这样他就不会影响到其他元素的排列布局了
- 使用
animation动画效果 代替postion:absolute移动元素
JS 方面:
-
避免频繁操作 DOM,使用文档碎片
documentFragment进行DOM操作,最后再把它添加到页面中 -
创建多个
calss来集中切换元素的样式 -
CSS3硬件加速(GPU加速)如果你为太多元素使用
CSS3硬件加速,会导致内存占用较大,也会有性能问题,有利也有弊吧~~常见的触发硬件加速的
CSS属性:- transform
- opacity
- filters
总结
以上就是本次分享的全部内容~~
如果觉得文章写得不错,对你有所启发的,请不要吝啬 点个 赞 和 关注 并在 评论区 留下你宝贵的意见哦~~😃