浏览器 - 重绘(repaint)重排(reflow)
浏览器 - 重绘(repaint)重排(reflow)
网页生成过程:
- HTML被HTML解析器解析成DOM 树
- css则被css解析器解析成CSSOM 树
- 结合DOM树和CSSOM树,生成一棵渲染树(Render Tree)
- 生成布局(flow),即将所有渲染树的所有节点进行平面合成
- 将布局绘制(paint)在屏幕上
第四步和第五步是最耗时的部分,这两步合起来,就是我们通常所说的渲染。
渲染
网页生成的时候,至少会渲染一次。
在用户访问的过程中,还会不断重新渲染
重新渲染需要重复之前的第四步(重新生成布局)+第五步(重新绘制)或者只有第五个步(重新绘制)。
重排比重绘大:
大,在这个语境里的意思是:谁能影响谁?
- 重绘:某些元素的外观被改变,例如:元素的填充颜色
- 重排:重新生成布局,重新排列元素。
就如上面的概念一样,单单改变元素的外观,肯定不会引起网页重新生成布局,但当浏览器完成重排之后,将会重新绘制受到此次重排影响的部分。
比如改变元素高度,这个元素乃至周边dom都需要重新绘制。
也就是说:"重绘"不一定会出现"重排","重排"必然会出现"重绘"
重排(reflow)
概念
当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
重排也叫回流,重排的过程以下面这种理解方式更清晰一些:
回流就好比向河里(文档流)扔了一块石头(dom变化),激起涟漪,然后引起周边水流受到波及,所以叫做回流
常见引起重排属性和方法
任何会改变元素几何信息(元素的位置和尺寸大小)的操作,都会触发重排,下面列一些栗子:
- 添加或者删除可见的DOM元素;
- 元素尺寸改变——边距、填充、边框、宽度和高度
- 内容变化,比如用户在input框中输入文字
- 浏览器窗口尺寸改变——resize事件发生时
- 计算 offsetWidth 和 offsetHeight 属性
- 设置 style 属性的值
width height margin padding
display border position overflow
clientWidth clientHeight clientTop clientLeft
offsetWudth offsetHeight offsetTop offsetLeft
scrollWidth scrollHeight scrollTop scrollLeft
scrollIntoView() scrollTo() getComputedStyle()
getBoundingClientRect() scrollIntoViewIfNeeded()
重排影响的范围
由于浏览器渲染界面是基于流失布局模型的,所以触发重排时会对周围DOM重新排列,影响的范围有两种:
- 全局范围:从根节点html开始对整个渲染树进行重新布局。
- 局部范围:对渲染树的某部分或某一个渲染对象进行重新布局
局部范围重排
用局部布局来解释这种现象:把一个dom的宽高之类的几何信息定死,然后在dom内部触发重排,就只会重新渲染该dom内部的元素,而不会影响到外界。
尽可能的减少重排的次数、重排范围:
重排需要更新渲染树,性能花销非常大:
它们的代价是高昂的,会破坏用户体验,并且让UI展示非常迟缓,我们需要尽可能的减少触发重排的次数。
重排的性能花销跟渲染树有多少节点需要重新构建有关系:
所以我们应该尽量以局部布局的形式组织html结构,尽可能小的影响重排的范围。
而不是像全局范围的示例代码一样一溜的堆砌标签,随便一个元素触发重排都会导致全局范围的重排。
重绘(Repaints)
概念
当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
常见的引起重绘的属性
color border-style visibility background
text-decoration background-image background-position background-repeat
outline-color outline outline-style border-radius
outline-width box-shadow background-size
浏览器的渲染队列
eg:
思考以下代码将会触发几次渲染
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
根据我们上文的定义,这段代码理论上会触发4次重排+重绘,因为每一次都改变了元素的几何属性,实际上最后只触发了一次重排,这都得益于浏览器的渲染队列机制:
当我们修改了元素的几何属性,导致浏览器触发重排或重绘时。它会把该操作放进渲染队列,等到队列中的操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作。
- 强制刷新队列
div.style.left = '10px';
console.log(div.offsetLeft);
div.style.top = '10px';
console.log(div.offsetTop);
div.style.width = '20px';
console.log(div.offsetWidth);
div.style.height = '20px';
console.log(div.offsetHeight);
这段代码会触发4次重排+重绘,因为在console中你请求的这几个样式信息,无论何时浏览器都会立即执行渲染队列的任务,即使该值与你操作中修改的值没关联。
因为队列中,可能会有影响到这些值的操作,为了给我们最精确的值,浏览器会立即重排+重绘。
强制刷新队列的style样式请求:
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle(), 或者 IE的 currentStyle
我们在开发中,应该谨慎的使用这些style请求,注意上下文关系,避免一行代码一个重排,这对性能是个巨大的消耗
重排优化
分离读写操作
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
console.log(div.offsetLeft);
console.log(div.offsetTop);
console.log(div.offsetWidth);
console.log(div.offsetHeight);
还是上面触发4次重排+重绘的代码,这次只触发了一次重排:
在第一个console的时候,浏览器把之前上面四个写操作的渲染队列都给清空了。剩下的console,因为渲染队列本来就是空的,所以并没有触发重排,仅仅拿值而已。
样式集中改变
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
虽然现在大部分浏览器有渲染队列优化,不排除有些浏览器以及老版本的浏览器效率仍然低下:
建议通过改变class或者csstext属性集中改变样式
// bad
var left = 10;
var top = 10;
el.style.left = left + "px";
el.style.top = top + "px";
// good
el.className += " theclassname";
// good
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
缓存布局信息
// bad 强制刷新 触发两次重排
div.style.left = div.offsetLeft + 1 + 'px';
div.style.top = div.offsetTop + 1 + 'px';
// good 缓存布局信息 相当于读写分离
var curLeft = div.offsetLeft;
var curTop = div.offsetTop;
div.style.left = curLeft + 1 + 'px';
div.style.top = curTop + 1 + 'px';
离线改变dom
- 隐藏要操作的dom
在要操作dom之前,通过display隐藏dom,当操作完成之后,才将元素的display属性为可见,因为不可见的元素不会触发重排和重绘。
dom.display = 'none'
// 修改dom样式
dom.display = 'block'
- 通过使用DocumentFragment创建一个dom碎片,在它上面批量操作dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
- 复制节点,在副本上工作,然后替换它!
position属性为absolute或fixed
position属性为absolute或fixed的元素,重排开销比较小,不用考虑它对其他元素的影响
优化动画
可以把动画效果应用到position属性为absolute或fixed的元素上,这样对其他元素影响较小
动画效果还应牺牲一些平滑,来换取速度,这中间的度自己衡量:启用GPPU加速
此部分来自优化CSS重排重绘与浏览器性能
GPU(图像加速器):
GPU 硬件加速是指应用 GPU 的图形性能对浏览器中的一些图形操作交给 GPU 来完成,因为 GPU 是专门为处理图形而设计,所以它在速度和能耗上更有效率。
GPU 加速通常包括以下几个部分:Canvas2D,布局合成, CSS3转换(transitions),CSS3 3D变换(transforms),WebGL和视频(video)。
/*
* 根据上面的结论
* 将 2d transform 换成 3d
* 就可以强制开启 GPU 加速
* 提高动画性能
*/
div {
transform: translate3d(10px, 10px, 0);
}
浏览器 - 重绘(repaint)重排(reflow)的更多相关文章
- 什么是回流(重排 reflow)?什么是重绘(repaint)?如何减少回流、重绘?
什么是回流(重排 reflow)? 回流(重排 reflow):对DOM树进行渲染,只要修改DOM或修改元素的形状大小,就会触发reflow,reflow的时候,浏览器会使已渲染好受到影响的部分失效, ...
- 页面重绘(repaint)和回流(reflow)
前言 页面显示到浏览器上的过程: 1.1.生成一个DOM树. 浏览器将获取到的HTML代码解析成1个DOM树,包含了所有标签,包括display:none和动态添加的节点. 1.2.生成样式结构体. ...
- 回流(reflow)与重绘(repaint)
回流(reflow)与重绘(repaint) 很早之前就听说过回流与重绘这两个名词,但是并不理解它们的含义,也没有深究过,今天看了一套网易的题目,涉及到了这两个概念,于是想要把它们俩弄清楚... 一. ...
- 浏览器渲染详细过程:重绘、重排和 composite 只是冰山一角
https://juejin.im/entry/590801780ce46300617c89b8 渲染 这张很经典的图许多人都看过,其中的概念大家应该都很熟悉,也就是这么几个步骤:js修改dom结构或 ...
- 关于重绘and重排
在研究CSS3动画性能的时候,看到了重排两个字. 突然想到自己虽然听说过这么个东东,但一直也没深入研究之. 趁着当下正好有研究的劲头,所以一不做二不休,把这个point也给学习了. 同样是一番查找资料 ...
- CSS新特性contain,控制页面的重绘与重排
在介绍新的 CSS 属性 contain 之前,读者首先需要了解什么是页面的重绘与重排. 之前已经描述过很多次了,还不太了解的可以先看看这个提高 CSS 动画性能的正确姿势. OK,下面进入本文正题, ...
- 浏览器的重绘与回流(Reflow & Repaint)介绍
重绘 当页面元素样式改变不影响元素在文档流中的位置时(如background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行重新绘制操作. 回流 当改变 ...
- 页面优化,谈谈重绘(repaint)和回流(reflow)
一.前言 偶尔在面试过程中遇到过重汇与回流reflow的问题,毕竟页面优化也是考核一个开发者能力的关键之一,上篇文章聊了下documentfragment也是为了减轻回流问题,那么本篇文章好好介绍下重 ...
- 前端性能优化--回流(reflow)和重绘(repaint)
HTML加载时发生了什么 在页面加载时,浏览器把获取到的HTML代码解析成1个DOM树,DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等. 浏览器把所有样 ...
- DOM的回流和重绘(重排、重绘)
什么是DOM回流? 页面渲染时,我们对HTML结构简单的增删查改时,浏览器会对所有的dom进行重新排序,这就i是DOM回流,严重影响浏览器性能 DOM的回流和重绘: **DOM的回流**:当页面中元素 ...
随机推荐
- 旋转卡壳(求凸包直径)学习笔记 | 题解 P1452 [USACO03FALL]Beauty Contest G /【模板】旋转卡壳
前言 旋转卡壳(Rotating Calipers)可以在凸包上维护许多有用的信息,最常见的就是凸包直径(平面最远点对). 注意:本文不介绍所谓的 "人类智慧" 乱搞做法. 算法流 ...
- 作业详解及流程控制之for循环
作业详解及流程控制之for循环 目录 作业详解及流程控制之for循环 一.作业详解 1.根据用户输入内容打印其权限 2.编写用户登录程序 4.猜年龄的游戏 二.流程控制之for循环 三.while循环 ...
- 财务精度:BigInteger 与 BigDecimal
财务精度:BigInteger 与 BigDecimal 每博一文案 师父说: 人这一辈子,真地好难. 有些人,好着好着,忽然就变陌生了,有些手,牵着牵着,瞬间就放开了,有些路,走着走着,就失去了方向 ...
- 【学习笔记】XR872 GUI Littlevgl 8.0 移植(显示部分)
LVGL 介绍 官方网站:LVGL - Light and Versatile Embedded Graphics Library 源码位置:GitHub - lvgl/lvgl: Powerful ...
- TIM—高级定时器输出PWM
高级定时器输出PWM 主频144M,生成一个频率为1K,占空比为30%的PWM详细代码参考EVT例程PWM_Output 重要参数说明 TIM_TimeBaseInitStructure.TIM_Pe ...
- DJI Flight Simulator 无人机模拟器 功能介绍与使用说明
0 前言 无人机是当前非常火热的"相机设备",而大疆又是其中翘楚,功能丰富,可以说是一个将带着云台的智能手机放到了天空中.如果你有自己玩过旋翼无人机航模的话,可能会体会到大疆的另一 ...
- 程序员大杀器?带你玩转ChatGPT
作者:京东零售 栗鸿宇 ChatGPT简介 ChatGPT是一款基于AI技术的机器人对话软件,它能够与用户进行智能化的聊天对话,帮助用户解决日常生活中的问题,为用户提供丰富的信息和服务.它集成了海量知 ...
- 构建api gateway之 基于etcd实现动态配置同步
配置中心 在之前 tcp的yaml配置 介绍了如何监听yaml文件变化然后更新配置. 当然假如我们有很多实例,那么yaml改动将是非常痛苦的事情,那么如何做到配置文件统一管理,实时更新呢? 我们可以引 ...
- 重学SpringBoot. step7 高并发 秒杀
高并发 高并发最容易出现的问题就是数据安全能不能得到保障. 你需要保证速度,又需要保证数据安全,那么速度也必然会有所下降. 所以最简单的办法就是提升硬件.或者把Mysql换成MongoDB,加个Red ...
- SQL性能优化的47个小技巧,你了解多少?
大家好,我是哪吒. 1.先了解MySQL的执行过程 了解了MySQL的执行过程,我们才知道如何进行sql优化. 客户端发送一条查询语句到服务器: 服务器先查询缓存,如果命中缓存,则立即返回存储在缓存中 ...