<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!--
前言
重绘 当影响DOM元素可见性的属性发生变化 (如 color) 时, 浏览器会重新描绘相应的元素, 此过程称为重绘(Repaint)。
重绘触发场景
设置元素的透明度;
设置元素的背景色,字体颜色;
设置元素的可见性。
重排 当涉及到DOM节点的布局属性发生变化时,就会重新计算该属性,浏览器会重新描绘相应的元素,此过程叫重排(Reflow)。
重排触发场景
全局范围:从根节点html开始对整个渲染树进行重新布局;
局部范围:对渲染树的某部分或某一个渲染对象进行重新布局(DOM节点几何信息不曾改变,仅内部进行重排);
备注 重绘不一定导致重排,但重排一定会导致重绘。
性能优化:
重排的代价是高昂的,会破坏用户体验,并且让UI展示非常迟缓。通过减少重排的负面影响来提高用户体验的最简单方式就是尽可能的减少重排次数,重排范围。
减少重排范围:
当重排无可避免时,尽量避免全局范围的重排,进行局部范围的重排,尽量以局部布局的形式组织html结构,尽可能小的影响重排的范围。
尽可能在低层级的DOM节点上进行修改,避免通过父元素修改改变内部元素。
不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局。
减少重排次数:
样式集中改变,通过更改类名而不是直接修改样式或设置属性。
减少样式改变的次数,过滤修改过程中无必要的操作。
分离读写操作,DOM 的多个读操作(或多个写操作),应该放在一起。不要两个读操作之间,加入一个写操作。(这样多个写操作只会触发一次重排)
将 DOM 离线
使用 display:none,元素便不会再存在在渲染树中,相当于将其从页面上“拿掉”,我们之后的操作将不会触发重排和重绘,添加足够多的变更后,通过 display属性显示(另一次重排重绘),这样多次的重排重绘缩减成两次而已。
通过 documentFragment 创建一个 dom 碎片,在它上面批量操作 dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
复制节点,在副本上工作,然后替换相应节点。
使用 absolute 或 fixed 布局,使它脱离文档流,避免引起父元素及后续元素大量的回流。
缓存布局信息。
优化动画
把动画效果应用到 position属性为 absolute 或 fixed 的元素上,这样对其他元素影响较小,其次减少相应动画流畅性,否则Layout就会过于频繁,大量消耗CPU资源。
启用GPU加速GPU 硬件加速是指应用 GPU 的图形性能对浏览器中的一些图形操作交给 GPU 来完成,因为 GPU 是专门为处理图形而设计,所以它在速度和能耗上更有效率。
-->
<div id="app">
云测试
</div>
<style type="text/css">
</style>
</body>
<script type="text/javascript">
var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 重绘
s.backgroundColor = "#ccc"; // 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));// 添加node,再一次 回流+重绘
/*
* 因为 JavaScript 可以同时修改 DOM 和 CSSOM
* 由于浏览器不确定特定的JavaScript会做什么,所以它采取的预防措施是停止整个DOM构造,一般情况我们会将JavaScript
* 放到页面的底部,等页面要渲染结束再引进来,JavaScript是影响回流和重绘的关键。
*/
// 避免的方法一 样式集中改变 通过class和cssText进行集中改变样式
let el = document.getElementById('app');
console.log(el)
// 未优化的代码
var left = 10;
var top = 10;
el.style.left = left + "px";
el.style.top = top + "px";
// 优化后的代码
el.className += " className";//动态修改class
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";//通过cssText一次性添加
// 避免的方法二 缓存布局信息
// 未优化代码 强制刷新 触发两次回流
el.style.left = el.offsetLeft + 1 + 'px';
el.style.top = el.offsetTop + 1 + 'px';
// 优化的代码 缓存布局信息 相当于读写分离
var curLeft = el.offsetLeft;
var curTop = el.offsetTop;
el.style.left = curLeft + 1 + 'px';
el.style.top = curTop + 1 + 'px';
</script>
</html>