回流(重排)与重绘

您所在的位置:网站首页 回流操作的关键是什么 回流(重排)与重绘

回流(重排)与重绘

2024-07-16 22:12| 来源: 网络整理| 查看: 265

回流(重排)与重绘 浏览器的渲染原理“回流 / 重排”和“重绘”的定义何时发生回流何时发生重绘*** 如何减少回流 / 重绘一、 避免逐次改变样式,样式统一批量修改二、 使DOM脱离文档流,再作批量处理三、 缓存布局属性(需即时计算的属性)四、 position属性控制其脱离文档流五、 CSS3硬件加速

浏览器的渲染原理

浏览器的渲染原理步骤:

解析文档(HTML、SVG、XHTML),生成 DOM Tree解析CSS,生成 CSSOM Rule Tree根据 DOM Tree 和 CSSOM Rule 生成 Rendering Tree布局绘制

具体参考:

浏览器渲染原理、浏览器的解析

“回流 / 重排”和“重绘”的定义

①、回流的定义 :当Rendering Tree 中部分元素的尺寸大小、布局、隐藏等属性改变时,浏览器的布局需要调整,则需要重新渲染DOM。这个过程就叫回流。回流也叫重排(对整个页面进行重新排版)。

②、重绘的定义:当元素属性的改变不影响DOM Tree的结构,即不会影响浏览器的布局,只是“表象”发生变化(如background-color,visibility等),那么针对新样式对元素进行重新绘制。

③、二者的联系:

回流一定会引起重绘,重绘不一定引起回流。回流需要重新渲染DOM,也要重新处理Rendering Tree。即回流的开销比重绘要大。 何时发生回流

比较好理解的,DOM元素发生变化:

添加或删除可见元素元素的位置改变元素的尺寸大小改变(width,height,padding,border,margin等)

还有一类情况,即访问某些属性或调用某些方法或resize事件发生时:

属性

offsetTop、offsetLeft、offsetWidth、offsetHeightscrollTop、scrollLeft、scrollWidth、scrollHeightclientTop、clientLeft、clientWidth、clientHeight

方法:

getComputedStyle()getBoundingClientRect()currentStyle()

事件:

浏览器窗口尺寸改变,即resize事件页面初始化渲染

访问这些属性或调用这些方法,都是关乎元素在浏览器中的坐标位置,为了能够获得精确的值,浏览器需要进行即时计算。

嗯哼?即时计算?那就是要回流了。因为回流就是要计算元素布局位置构建DOM。

也就是说:当访问这些属性,或者调用这些方法,为了即时获得准确结果,浏览器干脆就重新计算元素位置大小,即发生一次回流!所以访问这些属性,调用这些方法,也会引起回流!

另外,resize事件,让浏览器窗口尺寸发生变化。而浏览器正是根据浏览器窗口大小来计算元素的位置和大小。那么浏览器的窗口大小发生变化,浏览器也需要重新去计算,那么也会发生回流。

总结:

① 关于DOM元素

添加或删除可见元素元素位置发生变化元素的尺寸大小发生变化页面初始化渲染

② 访问特定属性

offsetTop、offsetLeft、offsetWidth、offsetHeightscrollTop、scrollLeft、scrollWidth、scrollHeightclientTop、clientLeft、clientWidth、clientHeight

③ 调用特定方法

getComputedStyle()getBoundingClientRect()currentStyle()

④ 特定事件发生

浏览器窗口尺寸改变,即resize事件页面初始化渲染 何时发生重绘

引起重绘的因素比较单一 :仅仅改变的是某元素的外观或者说风格,不影响整个页面的布局,不会影响DOM。

*** 如何减少回流 / 重绘 一、 避免逐次改变样式,样式统一批量修改

如果是一个属性一个属性改,那么就会引起多次回流:

const ele = document.getElementById('test'); ele.style.width = '100px'; ele.style.height = '200px'; ele.style.border = '1px solid black'

引起三次回流。

解决① 可以合并到一个类里,统一添加:

adding-style{ width: 100px; height: 200px; border: 1px solid red; } const ele = document.getElementById('test'); ele.classList.add('adding-style');

解决② 使用cssText

const ele = document.getElementById('test'); ele.style.cssText += 'width: 100px; height: 200px; border: 1px solid red;'; 二、 使DOM脱离文档流,再作批量处理

若要对DOM元素作多次处理修改,不作任何处理的话则会引起多次回流;

处理思路:

使DOM元素脱离文档流对DOM元素作多次修改修改完,再把DOM元素带回文档流

具体实现:

解决① display:none、bababa处理、display:block

在进行一顿操作之前,先把DOM元素隐藏起来,操作完再让它显示出来。尽管隐藏和恢复显示会有2次回流,但至少隐藏之后不会因为一顿操作引起再多的回流。

const ele = document.getElementById('test'); ele.style.display = 'none'; // 隐藏成功,已脱离文档流,开始操作 // bababa // bababa // bababa // 操作完成,可以加回文档流 ele.style.display = 'block';

解决② 使用document fragment在DOM Tree之外建立一个子树

const ele = document.getElementById('test'); const fragment = document.createDocumentFragment(); // 对子树 fragment操作 // bababa // bababa // bababa // 添加回去 ele.appendChild(fragment);

解决③ 将待处理元素拷贝至一个脱离文档流的节点,处理完再代替原节点

const ele = document.getElementById('test'); const cloneNode = ele.cloneNode(true); // 处理脱离文档流的节点cloneNode // bababa // bababa // bababa // 拿cloneNode代替原节点 ele.parentNode.replaceChild(cloneNode,ele); 三、 缓存布局属性(需即时计算的属性)

上面说过,当访问特定属性,浏览器为保证精确性、即时性,会再一次计算元素,从而引发回流。

故可以把这些属性缓存起来再使用。

若不缓存,访问一次则引发一次回流:

const ele = document.getElementById('test'); ele.style.left = ele.offsetLeft + 1 + 'px'; //回流 ele.style.top = ele.offsetTop + 1 + 'px'; //回流

缓存到变量:

const ele = document.getElementById('test'); var curLeft = ele.offsetLeft; // 缓存到变量 var curTop = ele.offsetTop; // 缓存到变量 ele.style.left = curLeft + 1 + 'px'; //不会回流 ele.style.top = curTop + 1 + 'px'; //不会回流 四、 position属性控制其脱离文档流

position可以设置absolute、fixed,分别对应的是绝对定位和固定定位。

这两种定位都会使得元素脱离文档流。

那么把会多次回流的元素,将其设置为position:absolute或position:fixed。

脱离文档流,则发生变化也不会再引起回流。

五、 CSS3硬件加速

能够触发CSS3硬件加速的属性,彻底不会引起回流:

transformopacityfilters


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3