HTML页面渲染及优化详解

html-css019

HTML页面渲染及优化详解,第1张

页面渲染主要经过过程,具体介绍如下:

字节 → 字符 → 令牌 → 节点 → 对象模型

CSS树的生成和DOM树的生成基本是相同,如下

为什么会有CSS树

因为CSS关系也会有父子关系,就是css中常说的继承,一些样式如font-size等子元素会继承父级,所以会生成一套对应的CSS树和DOM树相对应。

通过上面的页面渲染介绍,很容易理解,重排就是重新布局页面结构,计算节点位置,而重绘就是绘制页面,只是一些样式如背景,颜色的变化等,不需要重新计算位置布局,所以 重排一定会导致重绘,但是重绘不一定导致重排。

导致页面重排主要有以下几点

上文中触发了四次重排,通过上文介绍,offsetTop,scrollTop,clientTop等属性的修改会触发重排,当浏览器获取DOM样式的时候立刻会执行一次重排,因为需要计算浏览器位置坐标,不会再继续观察下文是否还有DOM的操作,下文介绍浏览器渲染机制。

这种情况看似会触发四次重排,实际只会触发一次重排,现代浏览器基本都有渲染机制,浏览器会批量将样式修改一次性执行,批量修改完后再批量获取DOM位置,实际只触发一次。

等价于

通过上文,容易理解这种情况会触发两次重排,可以使用缓存(实际是分离读写)来优化。

这种情况会触发五次重排

避免设置大量的style属性,因为通过设置style属性改变结点样式的话,每一次设置都会触发一次reflow,所以最好是使用class属性实现元素的动画,设置position属性,最好是设为absoulte或fixed,脱离文档流,这样不会影响其他元素的布局。

事件委托原理:利用事件冒泡的特性,子元素都会冒泡到父元素上,当子元素如(li)元素都绑定事件时,可以只需绑定父元素(ul)来达到相同的效果,这样不仅减少了对dom的操作,减少重排或重绘,而且不用分配大量变量来保存dom,减少了内存。

委托

不要使用table布局,因为table中某个元素一旦触发了reflow,那么整个table的元素都会触发reflow。那么在不得已使用table的场合,可以设置table-layout:auto或者是table-layout:fixed这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围。

不要一个个修改属性,应通过一个class来修改

改为

参考文献

https://blog.csdn.net/b954960630/article/details/82317999

document.write重排整个页面

innerHTML可以重绘页面的一部分

1、构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树(Content Tree/DOM Tree);

2、构建渲染树(construct):解析对应的CSS样式文件信息(包括js生成的样式和外部css文件),而这些文件信息以及HTML中可见的指令(如<b></b>),构建渲染树(Rendering Tree/Frame Tree);

3、布局渲染树(reflow/layout):从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点所应该在屏幕上出现的精确坐标;

4、绘制渲染树(paint/repaint):遍历渲染树,使用UI后端层来绘制每个节点。

重绘(repaint或redraw):当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上。重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。

触发重绘的条件:改变元素外观属性。如:color,background-color等。

重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。

重绘和重排的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。

重排必定会引发重绘,但重绘不一定会引发重排。

触发重排的条件:任何页面布局和几何属性的改变都会触发重排,比如:

1、页面渲染初始化;(无法避免)

2、添加或删除可见的DOM元素;

3、元素位置的改变,或者使用动画;

4、元素尺寸的改变——大小,外边距,边框;

5、浏览器窗口尺寸的变化(resize事件发生时);

6、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;

7、读取某些元素属性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )

重绘发生的情况:

重绘发生在元素的可见的外观被改变,但并没有影响到布局的时候。比如,仅修改DOM元素的字体颜色(只有Repaint,因为不需要调整布局)

重绘重排的代价:耗时,导致浏览器卡慢。

1、浏览器自己的优化:浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。

2、我们要注意的优化:我们要减少重绘和重排就是要减少对渲染树的操作,则我们可以合并多次的DOM和样式的修改。并减少对style样式的请求。

(1)直接改变元素的className

(2)display:none;先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为display:block;这样的话就只引发两次重绘和重排;

(3)不要经常访问浏览器的flush队列属性;如果一定要访问,可以利用缓存。将访问的值存储起来,接下来使用就不会再引发回流;

//例如myElement元素沿对角线移动,每次移动一个像素。到500*500像素的位置结束。timeout循环体中可以这么做

//显然这种方法低效,每次移动都要查询偏移量,导致浏览器刷新渲染队列而不利于优化。好的办法是获取一次起始位置的值,然后赋值给一个变量。如下

(4)使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;

(5)将需要多次重排的元素,position属性设为absolute或fixed,元素脱离了文档流,它的变化不会影响到其他元素;

(6)如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document;

(7)尽量不要使用table布局。

不管页面发生了重绘还是重排,它们都会影响性能(最可怕的是重排 ,应尽量避免)

DOM:描述该页面的结构

render:描述 DOM 节点 (nodes) 在页面上如何呈现

当 DOM 元素的属性发生变化 (如 color) 时, 浏览器会通知 render 重新描绘相应的元素, 此过程称为 repaint。

如果该次变化涉及元素布局 (如 width), 浏览器则抛弃原有属性, 重新计算并把结果传递给 render 以重新描绘页面元素, 此过程称为 reflow。

这两个过程是很耗费浏览器性能的, 从 IE 系列和 Chrome 渲染页面速度上的差距即可看出渲染引擎计算对应值和呈现并不一定高效, 而每次对元素的操作都会发生 repaints 或 reflow, 因此编写 DOM 交互时如果不注意就会导致页面性能低下.

页面渲染的过程如下:

原文:

https://blog.csdn.net/sinat_37328421/article/details/54575638

https://blog.csdn.net/sophia_little/article/details/79613990

https://blog.csdn.net/qq_34255080/article/details/86235234

此处需要首先说明一下网页从HTML文件变成屏幕上的画面所经历的过程:

其中第4步为布局排列(flow),第5步为绘制(paint),这两部加起来也就是我们通常所说的 渲染

本次主题所说的重排与重绘便是指网页重新布局排列和重新绘制,英文概念分别为: Reflow , Repaint ,也有些文章中称之为 回流与重绘

重绘与重排与我们的前端性能有什么关系呢?

在Web前端页面的生命周期中,在网页生成时,浏览器会至少渲染一次页面,并且,在用户访问页面过程中,还可能会不断触发重排和重绘,不管页面发生了重绘还是重排,都会影响到网页的性能,尤其是其中的重排,会使我们付出高额的性能代价,因此我们应尽量避免。

那么哪些操作会引发重排与重绘呢?

当DOM的变化影响了元素的几何信息(元素的的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。

重排也叫回流,简单的说就是重新生成布局,重新排列元素。

以下情况会引发重排:

重排影响的范围:

由于浏览器渲染界面是基于流失布局模型的,所以触发重排时会对周围DOM重新排列,影响的范围有两种:

局部布局来解释这种现象:把一个dom的宽高之类的几何信息定死,然后在dom内部触发重排,就只会重新渲染该dom内部的元素,而不会影响到外界。

当一个元素的外观发生改变,但没有改变布局, 浏览器重新把元素外观绘制出来的过程,叫做重绘。

重排必定会引发重绘,但重绘不一定会引发重排。

重排的代价是高昂的,会破坏用户体验,并且让UI展示非常迟缓,重排重绘非常耗费资源,是导致网页性能低下的根本原因。

DOM变动和样式变动,都会触发重新渲染。但是,浏览器已经很智能了,会尽量把所有的变动集中在一起,排成一个队列,然后一次性执行,尽量避免多次重新渲染

如果写得不好,就会触发两次重排和重绘

我们应尽量减少重排,最简单的方式是: 1.减少重排次数;2.缩小重排范围

我们可以通过Chrome观察重排与重绘

打开开发者工具 =>点击Performance =>点击左侧小圆点 =>点击刷新页面 =>录制=>查看数据