浏览器加载, 解析, 和渲染过程

浏览器加载, 解析, 和渲染过程


一. 为什么要了解浏览器加载、解析、渲染这个过程?

好,我们先说一下,为什么要了解这些呢?如果想写出一个最佳实践的页面,就要好好了解。
- 了解浏览器如何进行加载,可以在引用外部样式文件,外部js时,将他们放到合适的位置,使浏览器以最快的速度将文件加载完毕。
- 了解浏览器如何进行解析,可以在构建DOM结构,组织css选择器时,选择最优的写法,提高浏览器的解析速率。
- 了解浏览器如何进行渲染,明白渲染的过程,在设置元素属性,编写js文件时,可以减少”reflow“”repaint“的消耗。
正文开始

二. 几个概念:

(1)Reflow(回流):浏览器要花时间去渲染,当它发现了某个部分发生了变化影响了布局,那就需要倒回去重新渲染。
(2)Repaint(重绘):如果只是改变了某个元素的背景颜色,文字颜色等,不影响元素周围或内部布局的属性,将只会引起浏览器的repaint,重画某一部分。

Reflow要比Repaint更花费时间,也就更影响性能。所以在写代码的时候,要尽量避免过多的Reflow。

三. 产生reflow 的原因:
1. 页面初始化的时候;
2. 操作DOM的时候;
3. 某个元素的尺寸改变的时候;
4. CSS 的属性发生改变的时候;
四. 减少 reflow/repaint

 (1) 不要一条一条地修改 DOM 的样式。与其这样,还不如预先定义好 css 的 class,然后修改 DOM 的 className。
 (2) 不要把 DOM 结点的属性值放在一个循环里当成循环里的变量。
 (3) 为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会 reflow 的。
 (4) 千万不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。

五. HTML页面加载和解析流程

1.用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件;

2.浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件;

3.浏览器又发出CSS文件的请求,服务器返回这个CSS文件;

4.浏览器继续载入html中<body>部分的代码,并且CSS文件已经拿到手了,可以开始渲染页面了;

5.浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码;

6.服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;

7.浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它;

8.Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。突然少了这么一个元素,浏览器不得不重新渲染这部分代码;

9.终于等到了</html>的到来,浏览器泪流满面……

10.等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript让浏览器换了一下<link>标签的CSS路径;

11.浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的CSS文件,重新渲染页面。


思考

编写CSS时应该注意:

CSS选择符是从右到左进行匹配的。从右到左!所以,#nav li 我们以为这是一条很简单的规则,秒秒钟就能匹配到想要的元素,但是,但是,但是,是从右往左匹配啊,所以,会去找所有的li,然后再去确定它的父元素是不是#nav。,因此,写css的时候需要注意:

  1. dom深度尽量浅。
  2. 减少inline javascript、css的数量。
  3. 使用现代合法的css属性。
  4. 不要为id选择器指定类名或是标签,因为id可以唯一确定一个元素。
  5. 避免后代选择符,尽量使用子选择符。原因:子元素匹配符的概率要大于后代元素匹配符。后代选择符;#tp p{} 子选择符:#tp>p{}
  6. 避免使用通配符,举一个例子,.mod .hd *{font-size:14px;} 根据匹配顺序,将首先匹配通配符,也就是说先匹配出通配符,然后匹配.hd(就是要对dom树上的所有节点进行遍历他的父级元素),然后匹配.mod,这样的性能耗费可想而知.
关于script标签的位置

现在,我们大家都会将script标签放在body结束标签之前,那原因是什么呢
我今天也做了一个测试。

<!DOCTYPE html><html><head>
    <meta charset="utf-8">
    <title>测试js代码位置</title>
    <script type="text/javascript">
        var item = document.getElementById("item");
        cosole.log(item);
    </script>
</head>
    <body>
        <div id="item" width="100px" height="100px">
            你好
        </div>
    </body>
</html>

上述代码中有一段js代码,要在控制台打印一个元素,我把script标签放在head里,控制台里打印出来的是null。

我又把js代码放在body结束标签之前,打印出来的就是div元素了

所以,通过这个简单的例子我们可以看到,js代码在加载完后,是立即执行的。
我又做了一个测试,在js代码里面写了一个死循环,把它放在head标签中:

<!DOCTYPE html>
<html>
    <head>
    <meta charset="utf-8">
    <title>测试js代码位置</title>
    <script type="text/javascript">
        var item = document.getElementById("item");
        while(true){
            console.log(1);
        }
    </script>   
    </head>
<body>
    <div id="item" width="100px" height="100px">
        你好
•   </div> 
</body>
</html>

一直在执行那个打印1的死循环,后面的body都没有加载渲染出来。所以,这个小例子,我们可以看出,js的下载和执行会阻塞Dom树的构建。

所以,Javascript的加载和执行的特点:

(1)载入后马上执行;

(2)执行时会阻塞页面后续的内容(包括页面的渲染、其它资源的下载)。原因:因为浏览器需要一个稳定的DOM树结构,而JS中很有可能有 代码直接改变了DOM树结构,

比如使用document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修 改DOM树,需要重新构建DOM树的情况,所以 就会阻塞其他的下载和呈现。
减少 JavaScript 对性能的影响的方法:

  1. 将所有的script标签放到页面底部,也就是body闭合标签之前,这能确保在脚本执行前页面已经完成了DOM树渲染。

  2. 尽可能地合并脚本。页面中的script标签越少,加载也就越快,响应也越迅速。无论是外链脚本还是内嵌脚本都是如此。

  3. 采用无阻塞下载 JavaScript 脚本的方法:
    (1)使用script标签的 defer 属性(仅适用于 IE 和 Firefox 3.5 以上版本);
    (2)使用动态创建的script元素来下载并执行代码;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值