DOM – Browser Reflow & Repaint
前言
没有深入研究过, 懂个概念就好, 等性能遇到问题在来看看.
以前写的笔记: 游览器 reflow
参考:
Reflow & Repaint
repaint 是小的, 性能没有那么伤, 它只是换换颜色之类的.
reflow 是大的, 伤性能, 它会更动到排版布局.
所有插入 dom, 修改 dimension, padding 这类影响 layout 的东西都会导致 reflow.
translate 不会哦, positioin fixed 这种就 ok. 或者说它可以优化. 只是上层渲染, 不会影响整棵树.
when to render ?
当 JS 修改 DOM 时, 游览器并不是马上就渲染的, 它会有一个 timing.
通过 requestanimationframe 可以监听到它渲染了没有. 它不定时的, 依据各种 CPU / GPU 繁忙程度之类的去决定.
所以呢, 可能 JS 修改了多个属性, 但是其实游览器是一次性 reflow, repaint 的.
getBoundingClientRect & window.getComputedStyle
有传言说 getBoundingClientRect 和 getComputedStyle 会导致 reflow.
以前我都不太敢用, 后来才明白它的意思是.
如果 JS 修改了 DOM, 在游览器还没有决定什么时候渲染前, JS 又调用了 getBoundingClientRect.
那么游览器就必须马上去渲染, 这样才能给出准确的 rect. 所以说调用后就会 reflow.
但前提是游览器有需要渲染的东西而它还没有执行渲染. 一旦执行了渲染, 你连续调用 100 次 getBoundingClientRect 它也不会再去 reflow 了.
它怎么可能这么蠢呢. 是我以前蠢.. 哈哈
除了 getBoundingClientRect, getComputedStyle 还有许多操作都会导致提前 reflow 哦,比如 scroll,focus 等等。
Best practice
比如我想 resize table 的每一个 column width。
假如我 for loop 每一个 column,get widest cell then update all column cell to widest。
这样就不好,因为 for loop 的每一次都是一读一写,这样会一直 reflow。
好的做法是 for loop 读取每一个 column 的 widest cell,然后再 for loop 一次 update all column cell to widest。
这样就从 "读写(reflow)读写(reflow)读写(reflow)" 变成了 "读读读写写写(reflow)",最终只 reflow 一次。
具体例子
有一个 h1
<h1>Hello World</h1>
一开始它是 display none
h1 {
display: none;
opacity: 0;
transition: opacity 5s;
}
h1.showing {
display: unset;
}
h1.shown {
opacity: unset;
}
我们同时给它添加 showing 和 shown class
const h1 = document.querySelector('h1')!;
window.setTimeout(() => {
h1.classList.add('showing');
h1.classList.add('shown');
}, 1000);
它不会有 fade in 的效果,因为游览器同时渲染了 display block 和 opacity 1。(总共渲染 1 次而已)
在两行代码之间加入一些会导致 reflow 的代码
h1.classList.add('showing');
document.body.offsetHeight;
h1.classList.add('showed');
这时就会有 fade in 效果了,因为第一次渲染发生在 document.body.offsetHeight 之前,它只渲染了 display block。
而第二次才渲染 opacity 1。(总共渲染了 2 次)
但凡我们要拿的 information 涉及到布局,十之八九会导致 reflow。
所以一定要切记,如果我们修改了 DOM 又要拿 information 就要很小心,information 最好是可以提前拿啦 (除非你真的是想立刻拿到修改 和 render 后的 information)。
另外一点,调用 getComputedStyle 函数不会导致 reflow 什么的
h1.classList.add('showing');
window.getComputedStyle(h1);
h1.classList.add('showed');
// 只会渲染 1 次而已
但是拿 computedStyle 的属性会导致 reflow
h1.classList.add('showing');
window.getComputedStyle(h1).color;
h1.classList.add('showed');
// 会渲染 2 次
所以同样的,要拿 information 请尽早。
我个人的习惯是把 DOM 操作 wrap 在 requestAnimationFrame 里面,然后里面不做任何的 read information,一定是先把要的 information read 出来,最后才 write。
另外一点,query element (e.g. querySelector, querySelectorAll) 是不会导致立刻 reflow 的
const h1 = document.querySelector('h1')!;
window.setTimeout(() => {
h1.classList.add('showing');
const ww = document.createElement('div');
ww.classList.add('showing');
document.body.appendChild(ww);
const length = document.body.querySelectorAll('.showing').length;
window.setTimeout(() => {
console.log(length);
}, 1000);
h1.classList.add('showed');
}, 1000);
上面只会渲染一次,不会有 fade in 效果。(注:console 会导致 reflow 所以我才用 setTimeout wrap 它起来)
DOM – Browser Reflow & Repaint的更多相关文章
- 如何优化你的JS脚本来减少reflow/repaint?
如何优化你的脚本来减少reflow/repaint?1. 避免在document上直接进行频繁的DOM操作,如果确实需要可以采用off-document的方式进行,具体的方法包括但不完全包括以下几种: ...
- ♫【网站优化】Reflow / Repaint
web移动开发最佳实践之js篇 浏览器的回流与重绘 by 张盛志 DOM性能瓶颈与Javascript性能优化 浏览器的渲染原理简介 其中一个跟浏览器有关的原因,那就是浏览器需要花时间.花精力去渲染. ...
- 浏览器如何减少 reflow/repaint
1.不要一条一条地修改 DOM 的样式.与其这样,还不如预先定义好 css 的 class,然后修改 DOM 的 className. 2)把 DOM 离线后修改.如: 使用 documentFrag ...
- 浏览器的回流与重绘 (Reflow & Repaint)
写在前面 在讨论回流与重绘之前,我们要知道: 浏览器使用流式布局模型 (Flow Based Layout). 浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了 ...
- 介绍回流与重绘(Reflow & Repaint),以及如何进行优化?
前言 回流与重绘对于前端来说可以说是非常重要的知识点了,我们不仅需要知道什么是回流与重绘,还需要知道如何进行优化.一个页面从加载到完成,首先是构建DOM树,然后根据DOM节点的几何属性形成render ...
- Reflow & Repaint
http://www.phpied.com/rendering-repaint-reflowrelayout-restyle/ http://segmentfault.com/a/1190000002 ...
- 浏览器的重绘与回流(Reflow & Repaint)介绍
重绘 当页面元素样式改变不影响元素在文档流中的位置时(如background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行重新绘制操作. 回流 当改变 ...
- 前端性能优化 —— reflow(回流)和repaint(重绘)
简要:整个在浏览器的渲染过程中(页面初始化,用户行为改变界面样式,动画改变界面样式等)reflow(回流)和repaint(重绘) 会大大影响web性能,尤其是手机页面.因此我们在页面设计的时候要尽量 ...
- 前端性能优化 —— reflow(回流/重排)和repaint(重绘)
简要:整个在浏览器的渲染过程中(页面初始化,用户行为改变界面样式,动画改变界面样式等)reflow(回流)和repaint(重绘) 会大大影响web性能,尤其是手机页面.因此我们在页面设计的时候要尽量 ...
- 前端性能优化----reflow(回流)和repaint(重绘)
什么是reflow和repaint(原文链接:http://www.cnblogs.com/Peng2014/p/4687218.html) reflow:例如某个子元素样式发生改变,直接影响到了其父 ...
随机推荐
- Pandas库学习笔记(6) -- Pandas 基本方法
Pandas 基本方法实例 到目前为止,我们了解了三个Pandas DataStructures以及如何创建它们.由于它在实时数据处理中的重要性,因此我们将主要关注DataFrame对象,并讨论其他一 ...
- 三星app移植修复(app反编译修改)
工具: apktool ADT 命令: 反编译 java -jar apktool.jar d test.apk 重打包 java -jar apktool.jar b test 签名使用ADT sm ...
- 【微信小程序】 全局数据共享
1.什么是全局数据共享 全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题. 开发中常用的全局数据共享方案有: Vuex.Redux. MobX等. 2.小程序中的全局数据共享方案 在小 ...
- 【Centos6】时间同步问题
解决方案参考: https://www.cnblogs.com/webnote/p/5751758.html centos6并不会主动同步时间 上一次关机,将时间停留了 使用硬件时间同步校准 [roo ...
- 【Uni-App】API笔记 P2
8.路由,跳转 一.保留当前页面并跳转到指定页面 使用uni.navigateBack可以返回到原页面. uni.navigateTo(OBJECT) OBJECT参数说明 参数 类型 必填 默认值 ...
- 【Mybatis-Plus】04 AR (Active Record)
AR模式,全称激活记录 具体操作更接近Hibernate一样的OOP操作方式影响数据库记录 比Hibernate操作更灵活更方便 上手: 首先User实体类需要继承Model类并泛型注入User类型 ...
- Jenkins API用户认证方式
1.概述 Jenkins的API可以通过用户名+密码或者用户名+Token的方式来进行认证,这篇文章以具体示例来说明具体的使用方式. 2.Jenkins环境 本文示例基于Jenkins 2.452.3 ...
- 控制自行车前进/后退/平衡等动作,有必要使用在控制方面使用人工智能算法吗,还是传统的PID算法就完全可以胜任?
直接说答案,用不到人工智能算法做控制,现在人工智能算法主要的应用领域为感知学习,比较典型的就是图像识别和自然语言对话系统,而在控制算法上人工智能的解决方案依然不是很成熟,目前世界上唯一一个宣布可以落地 ...
- 国产AI模型和美国顶级AI模型的距离在哪?—— 算力?算法?数据?
前段时间去了长春一汽,聊了Reinforcement Learning方面的工作,既是面试,也是谈了谈意向,最后全部OK,本打算是签合同了,结果HR说要求有三年的社保缴纳证明工作经验,最后说可以减到2 ...
- 强化学习 —— reinforce算法中更新一次策略网络时episodes个数的设置对算法性能的影响 —— reinforce算法中迭代训练一次神经网络时batch_size大小的不同设置对算法性能的影响
本文相关的博客:(预先知识) 强化学习中经典算法 -- reinforce算法 -- (进一步理解, 理论推导出的计算模型和实际应用中的计算模型的区别) 本文代码地址: https://gitee.c ...