页面呈现、回流、重绘

输入url到页面呈现

1.浏览器分析链接指向页面的url。
  URL的本质就是统一资源定位符。
  URL一般包括几大部分:
    protocol,协议头,譬如有http,ftp等
    host,主机域名或IP地址
    port,端口号
    path,目录路径
    query,即查询参数
    fragment,即 #后的hash值,一般用来定位到某个位置
  网络请求都是单独的线程
  每次网络请求时都需要开辟单独的线程进行,譬如如果URL解析到http协议,就会新建一个网络线程去处理资源下载。

2.浏览器向DNS请求解析url的IP地址。
  第1步,浏览器会检查缓存中有没有这个域名对应的解析过的IP地址,如果缓存中有,这个解析过程就将结束。
  第2步,如果用户的浏览器缓存中没有,浏览器会查找操作系统缓存,再找本机host文件中,是否有这个域名对应的DNS解析结果。
  第3步,主机向其本地域名服务器进行递归查询。
  第4步,本地域名服务器进行迭代查询,向根域名服务器查询,再向顶级域名服务器查询,再向权限域名服务器查询,告诉本地域名服务器ip地址,本机域名服务器再把ip告诉本机。

3.TCP建立连接(SYN同步位用于建立连接,ACK确认,ack确认号,seq初始序号)
三次握手

4.建立连接后,客户端开始向服务器发送http请求(包括请求行、请求头和请求体)
  请求行包括:方法(option,get,head,post,put,delete,trace,connect)
        请求资源的url
        http的版本

5.服务端接收到请求后,对数据进行处理,然后返回HTTP响应报文给客户端(包括状态行、响应头和响应体)
  状态行包括:状态码
           1xx:通知信息的
           2xx:成功( 200——表明该请求被成功地完成,所请求的资源发送回客户端)
           3xx:重定向(304——自从上次请求后,请求的网页未修改过,请客户端使用本地缓存)
           4xx:客户的差错(400——客户端有语法错误,服务器不能理解
                   401——请求未经授权
                   403——禁止访问【譬如可以是未登录时禁止】
                   404——资源未找到)
           5xx:服务器的差错(500——服务器内部错误
                    503——服务不可用)
        解释状态码的简单短语
        http的版本

6.TCP连接释放(FIN终止位用于建立释放,ACK确认,ack确认号,seq初始序号)四次挥手

7.最后浏览器解析渲染页面
  第1步,浏览器把获取到的HTML代码解析成1个DOM树,HTML中的每个tag都是DOM树中的1个节点,根节点就是我们常用的document对象。DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等。
  第2步,浏览器把所有样式(用户定义的CSS和用户代理)解析成样式结构体,在解析的过程中会去掉浏览器不能识别的样式,比如IE会去掉-moz开头的样式,而FF会去掉_开头的样式。
  第3步,完成文档解析后,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 会影响布局(layout),会占有空间。根据CSS2的标准,render tree中的每个节点都称为Box (Box dimensions),理解页面元素为一个具有填充、边距、边框和位置的盒子。
  第4步,一旦render tree构建完毕后,浏览器就可以根据render tree来绘制页面了。
  在解析html时,会遇到一些资源连接,此时就需要进行单独处理了。简单起见,这里将遇到的静态资源分为一下几大类:
  遇到CSS样式资源
  CSS资源的处理有几个特点:
  CSS下载时异步,不会阻塞浏览器构建DOM树
  但是会阻塞渲染,也就是在构建render时,会等到css下载解析完毕后才进行(这点与浏览器优化有关,防止css规则不断改变,避免了重复的构建)
  遇到JS脚本资源
  JS脚本资源的处理有几个特点:
  阻塞浏览器的解析,当解析过程中遇到<script>标签的时候,便会停止解析过程,转而去处理脚本,如果脚本是内联的,浏览器会先去执行这段内联的脚本,如果是外链的,那么先会去加载脚本,然后执行。在处理完脚本之后,浏览器便继续解析HTML文档。
  同时javascript的执行会受到标签前面样式文件的影响。如果在标签前面有样式文件,需要样式文件加载并解析完毕后才执行脚本。这是因为javascript可以查询对象的样式。
  浏览器的优化,在现在浏览器中,为了减缓渲染被阻塞的情况,现代的浏览器都使用了猜测预加载。当解析被阻塞的时候,浏览器会有一个轻量级的HTML(或CSS)扫描器(scanner)继续在文档中扫描,查找那些将来可能能够用到的资源文件的url,在渲染器使用它们之前将其下载下来(当然有并发上限),但是虽然脚本可以并行下载,解析过程仍然是阻塞的,也就是说必须这个脚本执行完毕后才会接下来的解析,并行下载只是一种优化而已
  defer与async,普通的脚本是会阻塞浏览器解析的,但是可以加上defer或async属性,这样脚本就变成异步了,可以等到解析完毕后再执行
注意,defer和async是有区别的: defer是延迟执行,而async是异步执行。
<script src="script.js"></script>没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script async src="script.js"></script>有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。因此脚本在代码中的顺序并不是脚本所执行的先后顺序,有可能后面出现的脚本先执行,同时会在window的load事件之前执行,但不确定在 DOMContentLoaded事件的前或后
<script defer src="myscript.js"></script>有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoaded事件触发前执行,因此最好只包含一个延迟脚本。
在这里插入图片描述
蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。
【扩展:
DOMContentLoaded,就是dom内容加载完毕(我们从打开一个网页说起。当输入一个URL,页面的展示首先是空白的,然后过一会,页面会展示出内容,但是页面的有些资源比如说图片资源还无法看到,此时页面是可以正常的交互,过一段时间后,图片才完成显示在页面。从页面空白到展示出页面内容,会触发DOMContentLoaded事件。而这段时间就是HTML文档被加载和解析完成。)在任何情况下,DOMContentLoaded 的触发不需要等待图片等其他资源加载完成。
load,页面上所有的资源(图片,音频,视频等)被加载以后才会触发load事件,简单来说,页面的load事件会在DOMContentLoaded被触发之后才触发。
我们在 jQuery 中经常使用的$(document).ready(function() { // ...代码... });其实监听的就是 DOMContentLoaded 事件,而$(document).load(function() { // ...代码... });监听的是 load 事件。在用jquery的时候,我们一般都会将函数调用写在ready方法内,就是页面被解析后,我们就可以访问整个页面的所有dom元素,可以缩短页面的可交互时间,提高整个页面的体验。】
   遇到img图片类资源
  遇到图片等资源时,直接就是异步下载,不会阻塞解析,下载完毕后直接用图片替换原有src的地方。

回流与重绘

  1. 当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。
  2. 当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。

注意:回流必将引起重绘,而重绘不一定会引起回流。

回流何时发生
当页面布局和几何属性改变时就需要回流。
1、添加或者删除可见的DOM元素;
2、元素位置改变;
3、元素尺寸改变——边距、填充、边框、宽度和高度
4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
5、页面渲染初始化;
6、浏览器窗口尺寸改变——resize事件发生时;
让我们看看下面的代码是如何影响回流和重绘的:

js 代码:

var s = document.body.style;
s.padding = "2px"; // 回流+重绘
s.border = "1px solid red"; // 再一次 回流+重绘
s.color = "blue"; // 再一次重绘
s.backgroundColor = "#ccc"; // 再一次 重绘
s.fontSize = "14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));

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

  1. 将多次改变样式属性的操作合并成一次操作。
      同一个DOM的多个属性改变可以写在一起(减少DOM访问,同时把强制渲染队列刷新的风险降为0)。
      js多次操作css样式的时候不如加class来的快。
      直接改变className,如果动态改变样式,则使用cssText(考虑没有优化的浏览器)
// 不好的写法
var left = 1;
var top = 1;
el.style.left = left + "px";
el.style.top = top + "px";
// 比较好的写法
el.className += " className1";
// 比较好的写法
el.style.cssText += "; 
left: " + left + "px; 
top: " + top + "px;";
  1. 让要操作的元素进行”离线处理”,处理完后一起更新
    a) 使用documentFragment或div等元素进行缓存操作,这个主要用于添加元素的时候,先把所有要添加到元素添加到1个div(这个div也是新加的),最后才把这个div append。引发一次回流和重绘;
    b) 使用display:none隐藏元素,然后对该元素进行所有的操作,最后再显示该元素。因对display:none的元素进行操作不会引起回流、重绘。只引发两次回流和重绘;
    c) 使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;
  2. 不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存,以后用的时候直接读取变量就可以了
// 别这样写
for(循环) {
el.style.left = el.offsetLeft + 5 + "px";
el.style.top = el.offsetTop + 5 + "px";
}
// 这样写好点
var left = el.offsetLeft,
top = el.offsetTop,
s = el.style; 
for (循环) { 
left += 10; 
top += 10; 
s.left = left + "px"; 
s.top = top + "px"; 
}
  1. 将需要多次重排的元素,position属性设为absolute或fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。如果要批量添加DOM,可以先让元素脱离文档流,操作完后再带入文档流,这样只会触发一次重排(fragment元素的应用)。

参考链接:
页面重绘和回流以及优化.
DOMContentLoaded与load的区别.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值