页面的渲染流程

本文详细介绍了浏览器的页面呈现过程,包括DOM树构建、样式解析和呈现树的生成。讨论了回流(布局改变)与重绘(样式更新)的区别,并列举了常见引发回流和重绘的操作,强调了频繁的回流和重绘对性能的影响。最后,通过示例展示了如何通过使用文档碎片减少回流次数以优化页面性能。
摘要由CSDN通过智能技术生成

 

1.页面呈现过程

 

不同的浏览器略微会有些不同。但基本上都是类似的

 

①.浏览器把html代码解析成1个Dom树,html中的每个tag都是Dom树中的1个节点,根节点就是我们常用的document对象。dom树就是html结构,里面包含了所有的html tag,包括用JS添加的元素。

 

②浏览器把所有样式(主要包括css和浏览器自带的样式设置)解析成样式结构体,在解析的过程中会去掉浏览器不能识别的样式。

 

③dom tree和样式结构体结合后构建呈现树(render tree),render tree有点类似于dom tree,但有区别,render tree能识别样式,render tree中每个node都有自己的style,而且render tree不包含隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到render tree中。但是visibility:hidden隐藏的元素还是会包含到render tree中的,因为visibility:hidden 会影响布局,会占有位置。

 

④一旦render tree构建完毕后,浏览器就根据render tree来绘制页面。

 

呈现树中有的文档树中一定有,文档树中有的呈现树中不一定有

 

2.回流与重绘:

回流/回档:页面的元素排版布局数量和节点在树中位置等发生变化;每个页面至少需要一次回流,在页面加载的时候。

重绘:按照文档树的结构,重新绘制页面、渲染;

 

① 当render tree中因为元素的数量,尺寸,布局,隐藏等改变而需要重新构建。这就称为回流或者回档(其实我觉得叫重新布局更简单明了些)。每个页面至少需要一次回流,就是在页面第一次加载的时候。

②当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。

③(面试,选择题,问答题就答上面)从上面可以看出,回流必将引起重绘,而重绘不一定会引起回流。

 

3.常见的回流和重绘操作

任何对render tree中元素的操作都会引起回流或者重绘

①添加、删除元素(回流+重绘)

② 隐藏元素,display:none(回流+重绘),visibility:hidden(只重绘,不回流)

③ 移动元素,比如改变top,left(jquery的animate方法就是,改变top,left不一定会影响回流),或者移动元素到另外1个父元素中。(重绘+回流)④ 对style的操作(对不同的属性操作,影响不一样)

⑤ 还有一种是用户的操作,比如改变浏览器大小,改变浏览器的字体大小等(回流+重绘)

 

4.重绘与回流操作的注意点

//重绘与回流操作的次数越多,计算机的性能消耗越大进行dom操作的时候,就要考虑

我们程序执行时,常常会操作页面,常常引起重绘/回流;频繁的重绘/回流会造成页面性能不好===>页面卡顿、迟缓、手机发烫

解决方案:尽量避免高频重绘、使用框架

创建一个“冰”元素来承载即将出现的元素

冰元素:dom里面是fragment

wx小程序里面是block

react里面是框架

举例:

创建一个100×100的表格

并给每一个单元格添加上当前时间。

    <style>

        #box td{

            border: 2px solid black;

        }

    </style>

    <table id="box"></table>

    <script>

        let box=document.querySelector("#box")

        for(let i=0;i<100;i++){

            let tr=document.createElement("tr")

            box.appendChild(tr)

            for(let j=0;j<100;j++){

                time=new Date().getTime()

                var tds=document.createElement("td")

                tds.innerHTML=time

                tr.appendChild(tds)

            }

        }

    </script>

这段代码回档了一万零一百次

花费了135ms

 

添加冰元素,不让其每次创建了都添加:

      let box=document.querySelector("#box")

        for(let i=0;i<100;i++){

            let tr=document.createElement("tr")

            let fra1=document.createDocumentFragment()//他在内存中,不在文档中

            box.appendChild(tr)

            for(let j=0;j<100;j++){

                time=new Date().getTime()

                var tds=document.createElement("td")

                tds.innerHTML=time

                tr.appendChild(tds)

            }

        }

        td.appendChild(fra1)//他自己不会添加到文档书中,但是他的子元素都会添加进去

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值