目录
什么是回流
什么是重绘
回流产生原因
导致回流发生的因素
如何减少回流与重绘
什么是回流
指的是浏览器为了重新渲染页面的需要而进行的重新计算元素的几何大小和位置,他的开销是非常大的,回流可以理解为渲染树需要重新进行计算,一般最好触发元素的重构,避免元素的回流;比如通过添加class来添加css样式,而不是直接在DOM上设置,当需要操作某一块元素的时候,最好使其脱离文档流,这样就不会引起回流了,比如设置position:absolute或者fixed,或者display:none,等操作结束后在显示。
回流(Reflow)是指布局引擎为frame计算图形的过程。 frame是一个矩形,拥有宽高和相对父容器的偏移。frame用来显示盒模型(content model), 但一个content model可能会显示为多个frame,比如换行的文本每行都会显示为一个frame。
当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。
什么是重绘
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
回流必将引起重绘,而重绘不一定会引起回流。
如果你的HTML变得很大很复杂,那么影响你JavaScript性能的可能并不是JavaScript代码的复杂度,而是页面的回流和重绘。
回流产生原因
- 初始化(Initial)。DOM载入后的第一次回流,将会遍历所有frame。
- 渐进(Incremental)。当一个frame发生渐进回流时,意味着它前面的元素都没有变, 而是它里面的元素变了。这会引起自底向上的作用。
- 改变大小(Resize)。元素的容器边界发生变化时,此时元素内部状态没变。 在计算自顶向下的布局约束的同时,可以复用内部状态。
- 样式改变(StyleChange)。整个frame树都应得到遍历。
- Dirty。当一个容器已经缓存了多个子元素的Incremental回流时,该容器出于Dirty的状态。
导致回流发生的因素
- 调整窗口大小,浏览器窗口尺寸改变——resize事件发生时
- 元素尺寸改变——边距、填充、边框、宽度和高度;改变字体大小
- 页面渲染初始化
- 元素位置改变
- 样式表变动
- 元素内容变化,尤其是输入控件
- CSS伪类激活
- DOM操作,添加或者删除可见的DOM元素
- offsetWidth, width, clientWidth, scrollTop/scrollHeight的计算, 会使浏览器将渐进回流队列Flush,立即执行回流。内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变
例题(多选):修改以下哪些CSS属性会导致回流(reflow)?
A、color
B、width
C、display
D、font-size
答案:BCD
如何减少回流与重绘
减少回流、重绘其实就是需要减少对render tree的操作(合并多次多DOM和样式的修改),并减少对一些style信息的请求,尽量利用好浏览器的优化策略。
1. 直接改变className,如果动态改变样式,则使用cssText
2. 让要操作的元素进行”离线处理”,处理完后一起更新
- a) 使用DocumentFragment进行缓存操作,引发一次回流和重绘;
- b) 使用display:none技术,只引发两次回流和重绘;
- c) 使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;
3.不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存
4. 让元素脱离动画流,减少回流的Render Tree的规模
5.避免逐项更改样式。最好一次性更改style属性,或者将样式列表定义为class并一次性更改class属性。
6.避免循环操作DOM。创建一个documentFragment或div,在它上面应用所有DOM操作,最后再把它添加到window.document。
7.避免循环读取offsetLeft等属性。在循环之前把它们存起来。
8.绝对定位具有复杂动画的元素。绝对定位使它脱离文档刘,否则会引起父元素及后续元素大量的回流。
例子:
var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));
一起学习,一起进步 -.- ,如有错误,可以发评论
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!