前端重排与重绘

前端中的重排(Reflow)和重绘(Repaint)是浏览器渲染页面时两个重要的过程,它们直接关系到页面的性能。以下是对这两个过程的详细解析:

一、重排(Reflow)

定义

重排也称为回流或重构,是指当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建的过程。这个过程需要浏览器重新计算元素的几何属性,并重新构建渲染树。

触发条件

  • 页面渲染初始化(无法避免)
  • 添加或删除可见的DOM元素
  • 元素位置的改变,或者使用动画
  • 元素尺寸的改变,包括大小、外边距、边框等
  • 浏览器窗口尺寸的变化(resize事件发生时)
  • 填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变
  • 读取某些元素属性,如offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE)等

性能开销

重排是一个相对耗时的过程,因为它需要浏览器重新计算元素的几何属性并重新构建渲染树。过多的重排会导致浏览器卡顿,影响用户体验。

二、重绘(Repaint)

定义

重绘是指一个元素外观的改变所触发的浏览器行为。当元素的可见外观被改变,但并没有影响到布局时,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。

触发条件

  • 改变元素外观属性,如color、background-color等

与重排的关系

重排必定会引发重绘,因为重排后需要重新绘制受影响的部分到屏幕中。但重绘不一定会引发重排,因为重绘只涉及元素的外观改变,而不涉及布局的重构。

三、优化策略

为了减少重排和重绘带来的性能开销,可以采取以下优化策略:

  1. 合并DOM和样式的修改:尽量合并多次的DOM和样式的修改,减少渲染树的操作次数。
  2. 使用CSS类名代替直接修改样式:通过改变元素的className来批量修改样式,而不是直接修改style属性。
  3. 缓存布局信息:在需要多次读取布局信息时,可以将其缓存起来,避免多次触发重排。
  4. 使用DocumentFragment:对于需要创建多个DOM节点的情况,可以先使用DocumentFragment创建一个临时的容器,然后在其中进行批量操作,最后再一次性添加到文档中。
  5. 避免使用table布局:table布局在修改时容易引发全局范围的重排,应尽量避免使用。
  6. 分离读写操作:在修改样式时,尽量先统一读取布局信息,然后再统一修改样式,避免在读写过程中触发多次重排。

通过以上优化策略,可以有效减少前端页面中的重排和重绘次数,提高页面的渲染性能。

当然可以,以下分别给出重排(Reflow)和重绘(Repaint)的实例:

重排(Reflow)实例

实例一:添加或删除DOM元素

当你向DOM树中添加或删除一个元素时,浏览器需要重新计算该元素及其周围元素的几何属性,这会导致重排。例如:

<div id="container">  
    <p>第一个段落</p>  
</div>  
<script>  
    var container = document.getElementById('container');  
    var newParagraph = document.createElement('p');  
    newParagraph.textContent = '新添加的段落';  
    container.appendChild(newParagraph); // 添加新元素,触发重排  
</script>

在这个例子中,当<p>元素被添加到#container中时,浏览器需要重新计算#container及其内部所有元素的布局,这会导致重排。

实例二:改变元素尺寸

改变元素的尺寸(如宽度、高度、外边距、边框等)也会触发重排。例如:

<div id="box" style="width: 100px; height: 100px; background-color: blue;"></div>  
<script>  
    var box = document.getElementById('box');  
    box.style.width = '200px'; // 改变宽度,触发重排  
</script>

在这个例子中,当#box元素的宽度被改变时,浏览器需要重新计算该元素及其可能受到影响的父元素和子元素的布局,这同样会导致重排。

重绘(Repaint)实例

实例一:改变元素颜色

改变元素的可见外观属性(如颜色、背景色等)而不影响布局时,会触发重绘。例如:

<div id="box" style="width: 100px; height: 100px; background-color: blue;"></div>  
<script>  
    var box = document.getElementById('box');  
    box.style.backgroundColor = 'red'; // 改变背景颜色,触发重绘  
</script>

在这个例子中,当#box元素的背景颜色被改变时,浏览器只需要重新绘制该元素的新颜色,而不需要重新计算布局,因此只触发了重绘。

实例二:改变元素文本内容

虽然改变元素的文本内容本身不一定会触发重排(如果文本内容没有超出元素的当前尺寸),但它可能会触发重绘,因为文本的渲染是元素外观的一部分。然而,如果文本内容的改变导致元素尺寸变化,那么也会触发重排。但在这里,我们仅考虑重绘的情况:

<div id="text-box">原始文本</div>  
<script>  
    var textBox = document.getElementById('text-box');  
    textBox.textContent = '新的文本内容'; // 改变文本内容,可能触发重绘(如果尺寸未变)  
</script>

在这个例子中,如果#text-box元素的尺寸足够大,能够容纳新的文本内容而不发生变化,那么浏览器只需要重新绘制新的文本内容,而不会触发重排。但如果新文本导致元素尺寸变化,则会同时触发重排和重绘。

需要注意的是,在实际开发中,重排和重绘往往不是孤立发生的,一个操作可能同时触发重排和重绘。此外,由于浏览器的优化机制,某些情况下可能会合并多个重排或重绘操作,以减少性能开销。

link标签:阻塞浏览器渲染(等css),不会阻塞DOM解析

style标签:阻塞DOM解析(JS进程->DOM解析线程、CSS解析线程)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值