Go to comments

JavaScript 渲染树

从现在开始,知识要进行一个深入的了解了,


什么是深入了解?

深入了解就是,原来只知道一个表面的东西,这么来的、这么用,

现在除了知道怎么来的、这么用,还要知道每一步是怎么来的,为什么这么用。


先说页面,

页面由HTML、CSS、Javascript这三个组合成的复合格式,

比如写一页面里面有HTML、CSS,最后会把页面展示给我们,但是在展示给我们的时候叫页面已经绘制完成了,

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
	div{
		width: 100px;
		height: 100px;
		background-color: aqua;
	}
</style>
</head>
<body>
	<div></div>
</body>
</html>


什么是绘制页面?

浏览器里面有一个渲染引擎,他会一行一行的绘制页面,

一行就是以一个像素的高度为单位,一行一行的这么绘制,

就像3D打印一样,一层一层把东西打印完,

绘制页面也是一样,会按照HTML、CSS语法去绘制页面。



然后页面上写一个的DIV元素,在写一个CSS样式

CSS是怎么和DIV元素联系到一起的?

怎么的一个加载顺序?

HTML和CSS是怎么执行的呢?


在系统内核的内部,他不认识我们写的DIV和CSS,他不会认识代码的,

内核是不会让他俩产生链接的,他是怎么办的呢?


浏览器里面的内核,会对页面进行一步一步的检索,

首先,先识别我们写的HTML代码

然后会把一大堆HTML代码(比如写了一大堆标签),形成一个叫domTree(dom树)的东西,


        <div></div>

        <span></span>

        <strong>

            <em></em>

        </strong>


一、domTree(dom树)

第一个概念叫dom树(domTreed),dom树会把整个页面的html代码一行一行去识别,识别后挂到一颗树形结构上,

树的顶端是html标签,树的左侧是head标签,右侧是body标签

未标题-1.png

浏览器会把html代码每一个节点,放到树形结构对应的位置里面去,

也就是说根据节点的排列方式,来绘制出一个dom树,叫dom节点的树形结构,

而且绘制dom树复核一个原则,叫深度优先原则。

1、什么叫深度优先?

深度优先就一条道走到黑,

看完html完之后,会先看左侧的head,然后再看head里面有什么东西,

head里面有meta绘制meta,有title绘制title,走到头之后,再反过来,

看另一条枝干body,深度优先原则。

2、怎么形成一个dom树呢?

形成dom树,要把这些节点都放在dom树上


    <div></div>

    <img src="xxx">

    <iframe src="xxx"></iframe>

    <img src="yyy">

    <span></span>

    <strong></strong>


现在有一个问题?

遇到div的时候,解析div把他结构放到dom树上,这个没问题,

碰到img的时候,是要等src把文件引入进来下载完,才把img节点挂在dom树上,还是看到img之后就把他挂到dom树上?

就是下载完才把img挂到dom树上,还是读完看到img就挂到dom树上了?


生成dom树的过程,叫dom节点的解析,解析的意思就是,认识这个节点是什么就可以了,

没必要把里面的所有的文字、所有的内容全加载完。

所以读到img的时候,系统一扫这个img标签,

该下载下载,不能下载完,就先把img节点挂在dom树上。


dom树的完成,代表所有dom节点的解析完毕,并不是所有dom节点的加载完毕

也就是说所有dom节点的加载完,一定在解析完发生之后,

下载完一定在解析完之后,解析完dom树就形成了,什么时候下载完要等一段时间,


比如图片很大要等一会,但是还没等下载完 解析完了,

这是一个异步发生的过程,就是同时发生的。


问一个问题

如果dom节点解析到最后了,一定意味着页面展示完毕了吗,或者说一定意味着页面里面的东西都下载完了吗?

不一定,因为解析完一定发生在前面。


接下来说css

二、cssTree(css树)

domTree(dom树)生成之后什么都不干,等着,

等cssTree树形成,


css树就是系统根据我们写的css,也形成跟dom树类似的一个树叫css树

跟dom节点都是对应的,css树跟dom树都一样深度优先,


css树生成完之后,会和dom树拼到一起,生产一个新的树叫randerTree

domTree + cssTree = randerTree

三、randerTree

randerTree形成完了之后,渲染引擎才会真正的开始绘制页面

按照randerTree里面每一条的规则去绘制页面,

每一条节点应该怎么绘制,在什么样的位置出现,符合什么样的原则。


js可以动态的改变dom结构,间接的影响css,

由于randerTree是页面最后绘制的依据,如果改变一个dom的结构(删除一个或增加一个dom节点),

dom树就变了,dom树一变randerTree就要重新去构建。


randerTree重新构建,这个页面就要重新绘制,从第一行绘制到最后,这样会浪费效率,

所以dom优化的前提是,尽量减少dom节点的添加、删除这种,

即使做的话,做好要一次性的做完,不要一会做一次,这样反复做,会反复进行reanderTree的构建,

这种reanderTree的重新,我们叫reflow重排或者重构,dom操作里面重构是效率最低的。

四、reflow重排

哪几种情况会触发重构呢?

1). dom节点的增删改查,

     具体的说是dom节点的删除、增加,会发生一系列改变

2). dom节点的宽高变化,

     上面一个方块宽高变了之后,会影响下面所有方块的位置,

     下面所有方块的位置都会重新绘制,这样也会重新构建reanderTree,

     凡是重新构建reanderTree的过程都是低效的过程,尤其的大刀阔斧的从根一起改,都会印象页面的效率

3). 位置变化

4). display:none变成了block,这些都算改变位置

5). offsetWidth、offsetLeft这些语法,感觉上是查看dom节点的宽度,dom节点的位置,怎么也会触发重排?

     当调用offsetWidth和offsetLeigth,会计算dom节点的宽度和高度,

     但是系统会基于这样的一个原则,系统会把reanderTree重新构建一遍,然后重新渲染页面,

     这样才能保证求出的结果是时实的,所以他会重构reanderTree,这时候也会触发重排。


具体的细则vip课程去讲,现在了解一个概念叫reflow重排,编程要避免重排,

还有一种效率也是低的,但是相比较而已,效率低的可以有情可原,叫repaint重绘

五、repaint重绘

比如给一个dom节点改变背景颜色,但凡改一个东西,reanderTree都会重新构建的,

只不过是基于什么重新构建,如果是基于css的颜色重新构建的话,不会全把reanderTree改变,

会把css树的一部分改变了,然后在对应的reanderTree上面,把那一部分进行改变,

也就是说影响比较小,重绘的只是这一部分,不会是整个页面都重绘


所以repaint浪费的效率就很小,是可以接受的,

比如改字体颜色,改背景图片,背景图片的位置随便改,不会影响元素。



Leave a comment 0 Comments.

Leave a Reply

换一张