页面重绘与回流

一.什么是页面的重绘与回流

浏览器在渲染一个页面的时候,从加载到完成,首先是构建DOM树,然后根据DOM节点的几何属性生成渲染树(不包括display:none,head节点但是会包括visibility:hidden节点),当渲染树构建完成,页面就根据DOM树开始布局了,渲染树也根据设置的样式对应的渲染这些节点。在这个过程中,回流与dom树和渲染树有关,重绘与渲染树有关。

比如我们删除一个dom节点,修改一个元素的宽高,这样就会导致页面的布局发生变化,DOM树的结构发生变化,引起dom树的重构,重构完成之后就会导致渲染树的重新渲染,这个过程就叫做回流

当我们修改一个元素的颜色,这并不会影响页面的布局,但是渲染树会重新渲染页面的样式颜色,这就是重绘

回流的代价是远远大于重绘的,回流一定导致重绘,但是重绘不一定导致回流。

二.常见的场景

回流常见于元素的尺寸,布局,隐藏等Dom结构发生改变的情况
1.添加或者删除可见的dom元素
2.元素位置改变
3.元素尺寸改变(边距,填充,边框,高度和宽度)
4.内容改变(内容物引起的元素大小发生变化)
5.页面渲染初始化
6.浏览器尺寸改变
7.计算元素的偏移量属性(浏览器为了确保属性值的正确性会回流得到最新值,所以最好使用一个变量记录一下)

重绘常见于元素的颜色的样式发生改变的情况
1.改变字体
2.增加或者移除样式表
3.内容变化(input输入框)
4.激活CSS伪类
5.设置style属性值
6.计算offsetWidth和offsetHeight属性

三.如何优化浏览器的回流与重绘

1.将那些改变样式的操作集合在一次完事,直接改变className或者cssText
  • 使用cssText
const el = document.getElementById('test'); 
el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;'; 
  • 修改CSS的class
const el = document.getElementById('test'); 
el.className += ' active'; 
2.让要操作的元素进行离线处理,处理完事以后再一起更新

(1)使用DocumentFragment进行缓存操作,引发一次回流和重绘
(2)使用display:none,只引发两次回流和重绘。道理跟上面的一样。因为display:none的元素不会出现在render树

function appendDataToElement(appendToElement, data) {
    let li;
    for (let i = 0; i < data.length; i++) {
        li = document.createElement('li');
        li.textContent = 'text';
        appendToElement.appendChild(li);
    }
}
const ul = document.getElementById('list');
ul.style.display = 'none';
appendDataToElement(ul, data);
ul.style.display = 'block';

(3)使用cloneNode和replaceChild技术,引发一次回流和重绘(将原始元素拷贝到一个脱离文档流的节点中,修改节点之后,再替换原始元素)

const ul = document.getElementById('list');
const clone = ul.cloneNode(true);
appendDataToElement(clone, data);
ul.parentNode.replaceChild(clone, ul);
3.不要经常访问会引起浏览器flush队列的属性,非要高频访问的话建议缓存到变量;
4.将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位;
5.尽量不要使用表格布局,如果没有定宽,表格一列的宽度由最宽的一列决定,那么很可能在最后一行的宽度超出之前的列宽,引起整体回流造成table可能需要多次计算才能确定好其在渲染树中节点的属性,通常要花3倍于同等元素的时间。
6.避免触发同步布局事件

现代浏览器都会通过队列化修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。但是!当你获取布局信息的操作的时候,会强制队列刷新,比如当你访问以下属性或者使用以下方法:

  • offsetTop、offsetLeft、offsetWidth、offsetHeight
  • scrollTop、scrollLeft、scrollWidth、scrollHeight
  • clientTop、clientLeft、clientWidth、clientHeight
  • getComputedStyle()
  • getBoundingClientRect
function initP() {
    for (let i = 0; i < paragraphs.length; i++) {
        paragraphs[i].style.width = box.offsetWidth + 'px';
    }
}

改为

const width = box.offsetWidth;
function initP() {
    for (let i = 0; i < paragraphs.length; i++) {
        paragraphs[i].style.width = width + 'px';
    }
}

以上属性和方法都需要返回最新的布局信息,因此浏览器不得不清空队列,触发回流重绘来返回正确的值。因此,我们在修改样式的时候,最好避免使用上面列出的属性,他们都会刷新渲染队列。如果要使用它们,最好将值缓存起来

7.css3硬件加速,使用部分css3的属性不会引发页面的回流与重绘或者造成的影响比较小

四.浏览器渲染的过程

浏览器渲染过程

渲染过程大致如下:
1.解析HTML,生成DOM树,解析CSS,生成CSSOM树
2.将DOM树和CSSOM树结合,生成渲染树
3.回流(Layout):根据生成的渲染树,进行回流得到节点信息(位置,大小)
4.重绘(Painting):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
5.Display:将像素发送给GPU,展示在页面上
生成渲染树
生成渲染树

1.从DOM树的根节点开始遍历每个可见节点。
2.对于每个可见的节点,找到CSSOM树中对应的规则,并应用它们。
3.根据每个可见节点以及其对应的样式,组合生成渲染树。
不可见的节点:(渲染树只包含可见的节点)

  • 一些不会被渲染出来的点,比如:script,meta,link等
  • 一些通过css进行隐藏的节点。比如display:none。注意,利用visibility和opacity隐藏的节点,还是会显示在渲染树上的。只有display:none的节点才不会显示在渲染树上。

学习链接:
1.https://www.cnblogs.com/dujingjie/p/5784890.html
2.https://www.cnblogs.com/wanan-01/p/7732340.html
3.https://zhuanlan.zhihu.com/p/22181897
4.https://zhuanlan.zhihu.com/p/52076790

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352