首先了解浏览器的渲染过程
1、浏览器渲染过程
(截自chenjigeng作者的图)
- 浏览器采用流式布局;
- 解析HTML—DOM树,解析CSS—CSSOM树,DOM + CSSOM => 渲染树;
- 根据生成的渲染树,进行回流(layout),得到节点的位置、大小;
- 根据之前得到的信息,进行重绘(painting),得到节点的绝对像素;
- 将像素发送给GPU,节点绘制到页面上;
2、回流
发生机制:
- 页面初始渲染;
- 添加/删除元素;
- 位置、尺寸(包括边距大小、高度、宽度)、内容(文本、图片替换)变化;
- 浏览器窗口大小变化;
- display:none,脱离了文档流;
回流一定会触发重绘,而重绘不一定会回流
3、重绘
发生机制:
- 颜色
- visibility: hidden,元素还是占了位置的
4、优化机制
- 避免频繁使用0ffsetTop/Left/Width/Height、scrollTop/Left/Width/Height、clientTop/Left/Width/Height、width/height(大多浏览器是通过队列化修改、执行重排过程,而这些属性需要返回最近的值,浏览器就得清空队列,触发回流/重排);
const width = box.offsetWidth;
function initP() {
for (let i = 0; i < paragraphs.length; i++) {
// 每次循环都会读取offsetWidth,强制浏览器刷新队列,放到循环外避免这种情况
// paragraphs[i].style.width = box.offsetWidth + 'px';
paragraphs[i].style.width = width + 'px';
}
}
- 将动画效果应用到positions: absolute/fixed元素上,脱离文档流,避免父元素以及有影响的元素频繁的回流;
- JS方面,避免频繁操作样式、DOM;
const el = document.getElementById('test');
el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
// or
el.className += ' active';
- css3硬件加速(GPU加速),可以让transform、opacity、filters这些动画不会引起回流重绘;
5、扩展知识
vue中v-if与v-show的区别:
v-if:条件渲染,条件为false时是不做渲染的,切换过程中内部事件监听和子组件会适当的销毁和重建
;切换消耗较高;
v-show:无论是true还是false,元素都会渲染,使用display来控制显示隐藏
;初始渲染消耗较高,适合频繁切换
场景;
PS:学习的重绘和回流介绍问题回答作者