一起学重绘和回流

Symbol卢
• 阅读 1673

前言

Hello,大家好,我是Symbol卢,最近也比较忙,原本打算继续更新用大白话轻松搞定正则(上) 的文章,收到了大家的反馈帮助到了一些同学(一同学习的朋友),也是真的很开心😄 但是刚好遇见这次的征文由于某些原因就先写了这篇文章(偷偷的说:“用大白话轻松搞定正则 的下 也快写完了”),因为我的成长道路上也有很多的前辈给我很大的帮助,所以我会继续的传承下去;重绘和回流也是面试当中经常会被问到的一个问题,所以这篇文章咱就一起来学一下重绘和回流,从浏览器的渲染机制到重绘和回流,再到轻松搞定两道面试题。

浏览器的渲染机制

浏览器的渲染机制 用大白话来说就是,我们所写的HTMLCSS是通过某一个机制来将他们渲染成一个个漂亮的网页,这个机制就是浏览器的渲染机制。

浏览器渲染过程:

  • 处理 HTML 并构建 DOM
  • 处理 CSS 构建 CSS 规则树(CSSOM)
  • DOM 树 与 CSS 规则树 合并成一个渲染树(Render Tree)
  • 根据渲染树来布局,计算每个节点的位置
  • 调用 GPU 绘制,合成图层,显示在屏幕上

大家可以参考下面的图片(图片来源于网络)来理解浏览器的渲染过程:

一起学重绘和回流

  1. 浏览器会把HTML代码解析为一个DOM树, 在这个DOM树中的每一个节点,就是HTML的 中的每一个标签(DOM树的节点就是由HTML中的标签解析而来的);在DOM树中的节点里面包含了所有的HTML标签,这些HTMl标签其中包括display:none隐藏的标签(这个节点还在DOM树中,只不过是被隐藏掉了 ),还有用JS动态添加的元素(动态添加元素的js已经执行,这样才会把元素添加到DOM树中 )等。
  2. 解析完DOM树,才会去将CSS代码(和浏览器设置的默认样式,其中不同的浏览器的默认样式是不同的)解析为CSSOM ,在这个解析的过程浏览器会自动去除一些浏览器不认识或者错误的样式,比如低端浏览器无法识别的css3样式,IE会去掉-moz开头的样式,Firefox会去掉_开头的样式。
  3. DOM 树 与 CSS 规则树(CSSOM) 合并成一个渲染树(Render Tree),此时的Render Tree很像DOM树,但是它们的区别就是Render Tree 能识别样式,并且Render Tree的每一个节点都有自己的样式,而且Render Tree中不包含一些隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现。注意: visibility:hidden隐藏的元素还是会包含到Render Tree中的,因 visibility:hidden 会占有空间,影响布局(layout)。
  4. 有了Render Tree,浏览器有可以根据Render Tree来进行布局,计算每个节点的位置。
  5. 调用 GPU 进行绘制,合成图层,将绘制好的页面显示在屏幕上。

重绘 (Repaint)

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器只需要将新样式赋予给元素并重新绘制它,因此性能损耗比较低,这个过程称为重绘

常见的重绘操作

  1. 改变元素颜色
  2. 改变元素背景色

回流 (Reflow)

当页面中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程(这一过程中浏览器需要重新的进行计算,计算后重新的对页面布局)称为回流,又叫重排(重排可以理解为对页面重新的进行了排版)因此是较重的操作,性能损耗较高

常见的回流操作

  1. 页面初次渲染
  2. 浏览器窗口大小改变
  3. 元素尺寸/位置/内容发生改变
  4. 元素字体大小变化
  5. 添加或者删除可见的 DOM 元素
  6. 激活 CSS 伪类(:hover……)
  • 重点回流必定会触发重绘,重绘不一定会触发回流。重绘的开销较小,回流的代价较高

如何减少重排和重绘(提高性能)

由于回流和重绘会带来很大的性能开销,所以在开发中我们要尽量避免或减少回流和重绘的次数来提高性能

  1. 要避免频繁的去操作DOM,可以通过创建documentFragment,完成所有所有DOM操作后,最后再把它添加到文档中。
  2. 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
  3. 对具有复杂动画的元素使用绝对定位,使其脱离文档流,否则会引起父元素及后续元素频繁回流。
  4. 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。

面试题

display:none 与 visibility:hidden 的区别是什么?

display : none 隐藏对应的元素,在文档布局中不再分配空间(回流(重排)+重绘)

isibility:hideen 隐藏对应的元素,在文档布局中仍保留原来的空间(重绘)

使用 CSSdisplay:none 属性后,HTML 元素(对象)的宽度、高度等各种属性值都将“丢失”;而使用 visibility:hidden 属性后,HTML元素(对象)仅仅是在视觉上看不见(完全透明),而它所占据的空间位置仍然存在。

什么是重绘和重排,它们的区别是什么?

重绘:当页面元素样式的改变不影响布局时,浏览器重新对元素进行更新的过程叫做重绘。

重排:当页面元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程叫做重排也叫做回流。

区别:

  1. 重绘的性能开销较低,重排的性能开销较高;

  2. 回流(重排)一定会触发重绘,而重绘不一定会回流(重排)

历史好文

  1. 用大白话轻松搞定正则(上)

  2. js垃圾回收机制原理给你聊的明明白白

  3. ES11来了,不进来看看嘛

  4. 秒懂js作用域与作用域链

结束语

以上就是这篇文章的全部内容,希望对大家有帮助,这里不用打赏的哈,因为那些曾经帮助我的前辈们,也从来没有要求过打赏,大家可以给个👍(赞又不要钱),同样也 欢迎大家转发一起学重绘和回流

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Symbol卢 Symbol卢
2年前
用大白话轻松搞定正则(下)
前言本文是的一篇续文,建议大家在看本篇文章之前,先看,(正则基础好和大佬可以忽略),文章中可能有不足的地方,也希望大家可以在评论区提出来,大家一起学习(本人菜的抠脚),这篇文章也是断断续续的接近半个月才写完(主要也是因为忙,后来又遇见了双节的技术正文,于是就又先写了一起学重绘和回流这篇征文),最后大家一起来聊聊这篇水文吧!如果这篇文章对您有帮助,可以
Karen110 Karen110
2年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
京东云开发者 京东云开发者
6个月前
Java服务总在半夜挂,背后的真相竟然是... | 京东云技术团队
最近有用户反馈测试环境Java服务总在凌晨00:00左右挂掉,用户反馈Java服务没有定时任务,也没有流量突增的情况,Jvm配置也合理,莫名其妙就挂了
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这