JavaScript中的Repaint和Reflow
开发一个页面时,不可避免的需要进行repaint和reflow。也就只有以前的静态页面才会不存在repaint和reflow。repaint主要是针对某一个DOM元素进行的重绘,reflow则是回流,针对整个页面的重排。字面意思来说:repaint就是重绘,reflow就是回流。repaint和reflow的目的是:展示一个新的页面样貌。在开始说明这两个方法之前,我们先来看一下关于浏览器从接收到一个URL到解析和渲染的相关流程。
1、浏览器接收到URL到渲染完成的一个整体过程
假设是简单的http请求(GET),IPV4,无代理。
1)浏览器先查看浏览器缓存-系统缓存-路由器缓存,若缓存中有,请略过中间步骤,直接跳到第9步~若没有,则按照下面的步骤进行操作。
2)浏览器从url中解析出服务器的主机名,并将主机名转换成服务器的IP地址。PS:DNS查找域名的过程
3)浏览器从url中解析出端口号,默认80
4)浏览器建立一条与服务器的TCP连接(建立过程:三次握手)。PS:一个完整的TCP连接
5)浏览器通过TCP连接向服务器发送http请求,请求数据包。
6)服务器处理HTTP请求,返回响应。
7)浏览器检查HTTP响应是否为一个重定向(3XX结果状态码)、一个验证请求(401)、错误(4XX、5XX)等等,这些都需要根据具体情况分类处理。PS:浏览器对于常见HTTP状态码的反应
8)浏览器接收HTTP响应并且可能关掉TCP连接,或者是重新建立连接使用新情求,获得新响应。
9)浏览器解码响应,如果响应可以缓存,则存入缓存。
10)浏览器显示HTML页面。
11)浏览器发送请求获取嵌入在HTML中的资源(html,css,javascript,图片,音乐······),对于未知类型,会弹出对话框。
12)浏览器发送异步请求。
13)页面全部渲染结束。
2、浏览器解析和渲染过程
从图中,我们可以看到,浏览器解析大概分为四个流程,从解析html以构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树。具体的流程如下:
(1)解析HTML构建DOM树:渲染引擎开始解析HTML文档,转换树中的HTML标签或js生成的标签到DOM节点,它被称为---内容树。
(2)构建渲染树:解析css(外部css文件和样式元素以及js生成的样式),根据css选择器计算出节点的样式,创建另一个树---渲染树。
(3)布局渲染树:从根节点递归调用,计算每个元素的大小、位置等,给每个节点所应该出现在屏幕上的精确坐标。
(4)绘制渲染树:遍历渲染树。每个节点将使用UI后端来绘制。
值得注意的是,这个过程是逐步完成的,为了更好的用户体验,渲染引擎将会尽可能早的将内容呈现到屏幕上,并不会等到所有的html都解析完成之后再去构建和布局render树。它是解析完一部分内容就显示一部分内容,同时,可能还在通过网络下载其余内容。
3、什么是 repaint 和 reflow
一个页面由两部分组成:
- DOM : 描述该页面的结构
- render : 描述 DOM 节点 (nodes) 在页面上如何呈现
当 DOM 元素的属性发生变化 (如outline,visibility,background color时, 浏览器会通知 render 重新描绘相应的元素, 此过程称为 repaint。也就是说不涉及任何DOM元素的排版问题的变动为repaint,例如元素的color/text-align/text-decoration等等属性的变动。
如果该次变化涉及元素布局 (如 width), 浏览器则抛弃原有属性, 重新计算并把结果传递给 render 以重新描绘页面元素, 此过程称为 reflow。也就是说除上面所提到的DOM元素style的修改基本为reflow。例如元素的任何涉及长、宽、行高、边框、display等style的修改。
这两个过程是很耗费浏览器性能的, 从 IE 系列和 Chrome 渲染页面速度上的差距即可看出渲染引擎计算对应值和呈现并不一定高效, 而每次对元素的操作都会发生 repaints 或 reflow, 因此编写 DOM 交互时如果不注意就会导致页面性能低下。
但是,Reflow 的成本比 Repaint 的成本高得多的多。DOM Tree 里的每个结点都会有 reflow 方法,一个结点的 reflow 很有可能导致子结点,甚至父点以及同级结点的 reflow。在一些高性能的电脑上也许还没什么,但是如果 reflow 发生在手机上,那么这个过程是非常痛苦和耗电的。
4、何时会发生repaint 和 reflow
1)触发repaint
- color的修改,如color=#ddd;
- text-align的修改,如text-align=center;
- a:hover也会造成重绘。
- :hover引起的颜色等不导致页面回流的style变动。
- 等等太多
2)触发reflow
- width/height/border/margin/padding的修改,如width=778px;
- 动画,:hover等伪类引起的元素表现改动,display=none等造成页面回流;
- appendChild等DOM元素操作;
- font类style的修改;
- background的修改,注意着字面上可能以为是重绘,但是浏览器确实回流了,经过浏览器厂家的优化,部分background的修改只触发repaint,当然IE不用考虑;
- scroll页面,这个不可避免;
- resize页面,桌面版本的进行浏览器大小的缩放,移动端的话,还没玩过能拖动程序,resize程序窗口大小的多窗口操作系统。
- 读取元素的属性(这个无法理解,但是技术达人是这么说的,那就把它当做定理吧):读取元素的某些属性(offsetLeft、offsetTop、offsetHeight、offsetWidth、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、getComputedStyle()、currentStyle(in IE));
5、如何优化
1)不要一条一条地修改 DOM 的样式,尽量通过修改className来修改样式 。
2)把 DOM 离线后修改。如:
- 使用 documentFragment 对象在内存里操作 DOM。
- 先把 DOM 给 display:none (有一次 repaint),然后你想怎么改就怎么改。比如修改 100 次,然后再把他显示出来。
- clone 一个 DOM 节点到内存里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。
3)不要把 DOM 节点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这个结点的属性。
4)尽可能的修改层级比较低的 DOM节点。当然,改变层级比较底的 DOM节点有可能会造成大面积的 reflow,但是也可能影响范围很小。
5)为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是会大大减小 reflow 。
6)千万不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。
table元素一旦触发reflow就会导致table里所有的其它元素 reflow。在适合用table的场合,可以设置table-layout为auto或fixed,这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围。
7)尽可能少的修改元素style上的属性 。
8)通过cssText属性来设置样式值。
9)缓存Layout属性值 。
10)设置元素的position为absolute或fixed。
11)避免使用expression,他会每次调用都会重新计算一遍(包括加载页面)。
JavaScript中的Repaint和Reflow相关推荐
- javascript性能优化-repaint和reflow
repaint(重绘) ,repaint发生更改时,元素的外观被改变,且在没有改变布局的情况下发生,如改变outline,visibility,background color,不会影响到dom结构渲 ...
- 探讨css中repaint和reflow
前言: 页面设计中,不可避免的需要浏览器进行repaint和reflow.那到底什么是repaint和reflow呢.下面谈谈自己对repaint和reflow的理解,以及结合其他技术牛的讲解,谈谈如 ...
- css的repaint和reflow
css的repaint和reflow 浏览器为了重新渲染部分或整个页面,重新计算页面元素位置和几何结构(geometries)的进程叫做 reflow. 由于 reflow 是一种浏览器中的用户拦截( ...
- 笔记:JavaScript中的30个疑难杂症
JavaScript中的30个疑难杂症 目录 数据类型 表达式运算符和分支结构 内置对象 JS DOM JS BOM 函数对象 面向对象 typeof 和 instanceof JS数据类型: 原始类 ...
- 了解repaint与reflow的触发场景
感兴趣的可以看看哦~ 体现: repaint是某个DOM元素进行重绘: reflow是整个页面进行重排,也就是页面所有DOM元素渲染.(可能造成页面原来的规划打乱) 如何触发: style变动造成re ...
- 浅析 JavaScript 中的 函数 uncurrying 反柯里化
柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是 ...
- JavaScript中,this的绑定规则
对于 JavaScript 新手来说,this 是非常基础同时也难以理解的知识点. 比如下面的代码,this 指向就有三种方式. 在<你不知道的 JavaScript>一书中,我总算比较清 ...
- Javascript中undefined,NaN等特殊比较
以下内容转自: http://blog.csdn.net/hongweigg/article/details/38090093 1.问题:在Javascript中,typeof(undefined) ...
- Javascript中二进制数据处理方法
Javascript中二进制数据处理方法 转载于:https://www.cnblogs.com/motadou/archive/2012/02/19/2358514.html
最新文章
- jgit查询远程仓库_JAVA 使用jgit管理git仓库
- JVM实战与原理---内存回收策略
- LINQ是死是活?——很奇怪为什么会有这样的话题?
- html视频标签不显示,HTML视频标签无法正确显示视频
- ubuntu 编译安装nginx php mysql_ubuntu下安装nginx php mysql
- 车牌颜色识别现在的结果
- 计算机硬件技术基础 统计字符串strl中字符'a'的个数,汕头大学工学院830计算机基础综合历年考研真题202p.doc...
- Android 十大调试方法
- 如何使用 Buildah 构建容器镜像
- 传感技术复习笔记(10)——光纤传感器
- python编写密码登录程序_python初学之用户登录的实现过程(实例讲解)
- Panda3D双面渲染和3D法线的概念学习
- 频繁模式挖掘 (Frequent pattern mining):01 概念篇 (附例题)
- 初学博科YIGO2.0学习心得--下推
- 乱得那么认真|阿里小二办公桌上的秘密~内部流出
- 【有利可图网】PS教程:制造低多边形熊猫头像
- 【C语言】动态申请空间
- 大数据新闻生产的实践与反思
- python问题解决----把\xe6\xa8\xa1\这种字符转为普通汉字?
- MSP430寄存器的设置与作用
热门文章
- curl命令行发送POST/GET请求
- Adaptec HBA和RAID 的兼容性报告中又添新成员—— HGST Helium HDD
- 第一个Android应用 扫描宝 欲挑战传统扫描枪
- Nexpose漏洞扫描器
- 网上的视频下载到电脑上
- php可输入的下拉框,jQuery实现可输入搜索文字的下拉框实例代码
- response.setHeader参数、用法的介绍
- win7打开计算机 多窗口,Win7系统打开新的文件夹总会以新窗口的形式打开的解决方法...
- 机器人卫士密码箱密码忘了怎么办_机器人卫士小学信息技术教案
- 2019年最受欢迎的手机App