浏览器渲染页面过程

今天在某论坛上看到这么一个问题。

现在页面有个空div,我用js向里面插入一段html,然后获取div的高度,发现有时候得到的div的高度不准确,请问各位有什么方法解决一下。

简单点来说就是创建了dom以后,还未完全渲染,就去获取dom的高度,显然是会出问题的。代码如下,可找个图片自行体会:

<div id="bgImg"></div>

<script>
    document.body.scrollHeight;
    var odiv = document.getElementById('bgImg');
    odiv.innerHTML = '<img src="test.jpg">'
    var oHeight = odiv.scrollHeight;
    console.log(oHeight);
</script>

那么为了更好的理解这个问题,咱们今天来聊聊浏览器的渲染过程

  1. 解析HTML
  2. 解析CSS
  3. 构建Render Tree
  4. 布局(Layout)
  5. 绘制(Painting)

1. 解析HTML,构建DOM

浏览器获取到网页文件以后,怎么将代码生成美丽的页面呢?
首先需要将网站的结构搭建起来,类似于人的全身骨骼,解析HTML做的就是这个事情。解析HTML的所有标签,然后深度遍历生成DOM Tree,如图所示
DOM Tree

2. 解析CSS,构建CSSOM

有了骨骼以后,接下来就是确定长相了,这是CSS要做的事情。和解析HTML类似,CSS解析各种样式信息,生成网页的“外观”。但是有个问题,CSSA(class选择器)说,我喜欢蓝色,我家网页的所有文字都要是蓝色。CSSB(id选择器)就不乐意了,凭啥啊,我喜欢红色,我家的标题必须是红色。由于id选择器是亲生的,那就标题是红色的吧,于是不同选择器就有了不同的权重。最后生成CSSOM,如图所示:
在这里插入图片描述

2.5 JS脚本加载

为啥要2.5呢,因为浏览器解析文档,当遇到 <script>标签的时候,会立即解析脚本,停止解析文档(因为JS可以操作DOM和CSS,可能会改动DOM和CSS,所以继续解析会造成浪费)。如果脚本是外部的,会等待脚本下载完毕,再继续解析文档。所以常见的做法是将js放到页脚部分。

3. 构建Render Tree(呈现树)

骨骼和长相都有了,那就组合到一起呗,DOM和CSSOM根据一定的规则组合起来生成了Render Tree。如下图:
在这里插入图片描述

4. 布局(Layout)

创建渲染树后,接下来正式开工,确定各个元素的位置,包括元素在视图中的位置以及自身的大小,将其安置在浏览器的正确位置。

5. 绘制(Painting)

这个阶段,浏览器会遍历呈现树,并调用呈现器的“paint”方法,将前期所有的工作结合到一起,将网页的内容呈现出来。如果网页只是HTML+CSS,那么可能就到此结束了,but还有神奇的JS呢,请看回流和重绘。

回流(Reflow)和重绘(Repaint)

如果这个时候我写了用JS操作了DOM,将网页的所有元素设置float:left,那么问题来了,4、5的工作白干了,推翻从新再来。如果将所有元素的颜色改变了(并没有改变结构),比如color:red,还好还好,5的工作白干,推翻重来。可以想象一下,你辛辛苦苦加班一个月终于完成工作,产品经理来了一句:“好像要改一下需求…”

所以,尽可能少操作DOM,提升网页的性能。

【question】再回到最开始的这个问题,为什么获取到的DIV高度有问题?
刚开始一帆风顺,进行到第五步之后,又回到了第四步,此时如果是块级元素,就会设置好宽高,不存在任何问题。但如果是图片,此时是无法得知高度的(行内元素),只有等待第五步绘制以后再能确定高度。而图片的绘制需要时间,在尚未绘制完成的时候,获取到的高度则会出现问题。合理的解决方案是使用setTimeout延时获取div的高度。代码如下:

<div class="bgImg"></div>

<script>
    var odiv = document.getElementById('bgImg');
    odiv.innerHTML = '<img src="test.jpg">'
    
    setTimeout(() => {
        var oHeight = odiv.scrollHeight;
        console.log(oHeight);
    },100)
</script>

想要更详细的了解可以去《浏览器工作原理:新式网络浏览器幕后揭秘》

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值