二、浏览器

1. 浏览器输入URL后会发生什么?

1.1 URL解析

  • 地址解析。判断输入的是一个合法的URL还是一个待搜索的关键词,并且根据输入的内容进行自动完成、字符编码等操作

  • 使用HSTS,强制客户端使用HTTPS访问页面

  • 其他操作,如安全检查、访问限制等

  • 检查缓存
    task3-2 - 图1

1.2 DNS查询

1.2.1 DNS

DNS一般指域名系统,是互联网的一项服务。它作为将 域名 和 IP地址 相互映射的一个分布式数据库,能够使人更方便地访问互联网。

  • 域名服务器(级别由高到低):根域名服务器、顶级、本地~
  • 域名服务器(类型):主域名服务器、辅助、转发~

1.2.2 过程

DNS域名解析过程:

  • 浏览器缓存:若浏览器检查到不在自身缓存中,则调用系统库函数进行查询。

  • 操作系统缓存:浏览器检查操作系统缓存中有没有对应的已解析过的结果。(在此之前,)操作系统也有一个域名解析的过程,就是读取系统hosts文件,查找其中是否有域名对应的IP地址,浏览器会首先使用这个ip

  • 路由缓存:路由器自己的缓存

  • ISP DNS 缓存:ISP DNS 是客户端电脑上设置的首选DNS服务器,它们在大多数情况下都会有缓存

  • 如果以上步骤都找不到,则发生递归或者迭代查询。(常用递归与迭代相结合的查询方式)(都是先找到根)
    task3-2 - 图2

    • 迭代查询(又称重指引)
      要点1:右侧两个分别是“顶级”
      要点2:是本地DNS服务器以客户机的身份从根域名服务器开始再往其子域查询的方式
      要点3:每次返回给本地服务器的是最佳的查询点(下一步的提示)或者主机地址
      要点4:两个服务器之间有请求就必有返回

    • 递归查询
      要点1:一路查下去中间不返回,得到最终结果才返回信息(是浏览器到本地DNS服务器的过程)
      要点2:域名服务器将代替提出请求的客户机(下级DNS服务器)进行域名查询,若域名服务器不能直接回答,则域名服务器会在域各树中的各分支的上下进行递归查询,最终将返回查询结果给客户机,在域名服务器查询期间,客户机将完全处于等待状态。
      要点3:返回的结果只有 查询成功或查询失败 两种可能

task3-2 - 图3

建立TCP连接

参考详细内容:TCP握手协议

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。(确认好了IP和端口号,则可以向该IP地址对应的服务器的该端口号发起TCP连接请求。)大致总结为以下几个步骤:

  • 发送端首先发送一个带SYN的数据包给接收方;
  • 接收方收到后,回传一个带SYN/ACK的数据包表示传达确认信息。
  • 最后发送方再回传一个带ACK的数据包,代表握手结束。

发送HTTP请求

参考详细内容:HTTP报头协议

三次握手成功后,开始通讯,根据HTTP协议的要求,组织一个请求的数据包,里面含有请求的资源路径、身份信息等。

请求报文是由请求方法、请求URL、协议版本、可选的请求首部字段和内容实体构成的。

task3-2 - 图4

服务器处理请求

发送请求后,服务器响应请求,将数据返回给浏览器,数据可以是根据HTML协议组织的网页,里面包含页面的布局、文字等,也可以是图片或脚本程序。

响应报文基本上是由版本协议、状态码、用以解释状态码的原因短语、可选的响应首部字段以及实体主题构成。

task3-2 - 图5

返回响应结果

我们常见的情况,如果资源路径指定的资源不存在,服务器就会返回404错误。

(还有一些其他码,可再自行查阅)

关闭TCP连接

参考详细内容:四次挥手过程(连接终止协议)

task3-2 - 图6

浏览器解析HTML

浏览器自上而下逐行解析html文件,构建DOM树,在解析到外部的css和js文件时,向服务器发起请求下载资源。
当遇到外部 CSS 链接时,主线程调用网络请求模块异步获取资源,不阻塞而继续构建 DOM 树。当 CSS 下载完毕后,主线程在合适的时机解析 CSS 内容,构建 CSSOM 树。浏览器结合 DOM 树和 CSSOM 树构建 Render 树,并计算布局属性,每个 Node 的几何属性和在坐标系中的位置,最后进行绘制展示在屏幕上。

当遇到外部 JS 链接时,主线程调用网络请求模块异步获取资源,由于 JS 可能会修改 DOM 树和 CSSOM 树而造成回流和重绘,此时 DOM 树的构建是处于阻塞状态的。

预加载器

当浏览器被脚本文件阻塞时,预加载器(轻量级解析器)会继续解析后面的html,寻找需要下载的资源。若发现有需要下载的资源,预加载器开始接收这些资源。预加载器只能检索HTML标签中的URL,无法检测到使用脚本添加的URL,这些资源要等脚本代码执行才会获取。预解析并不改变DOM树,将这个工作留给主解析过程。

浏览器解析css,形成CSSOM树,当DOM树构建完成后,浏览器引擎通过DOM树和CSSOM树构造树渲染树。渲染树中包含可视节点的样式信息。

布局渲染

布局:通过计算得到每个渲染对象在可视区域中的具体位置(大小和位置),是一个递归的过程。

绘制:

将计算好的每个像素点信息绘制在屏幕上。

利用DOM和CSSOM构建一个渲染树,布局渲染树,绘制渲染树。

DOM树是由HTML文件中的标签排列组成,渲染树是在DOM树中加入CSS或HTML中的style样式而形成的。渲染树只包含需要显示在页面中的DOM元素,像元素或display属性值为none的元素都不在渲染树中。

在浏览器还没接收到完整的HTML文件时,它就开始渲染页面了,在遇到外部链入的脚本标签或样式标签或图片时,会再次发送http请求重复上述的步骤。在收到CSS文件后对已经渲染的页面重新渲染,加入他们应有样式,图片文件加载完立刻显示在相应位置。在这一过程中可能会出发页面重绘或重排。

2. DOM事件流

2.1 总述

事件流:可以理解成是事件执行的顺序流

DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。

task3-2 - 图7

DOM事件流最独特的性质是,文本节点也触发事件(在IE中不会),当鼠标单击“单击此文本”文本时会触发click事件,该事件的捕获阶段最先开始,从Document节点开始逐渐向下传播,直到“单击此文本”文本节点,事件进入目标阶段,在目标阶段结束之后,事件由“单击此文本”文本节点开始事件的冒泡阶段,直到Document节点为止。

2.2 两种事件流

(从兼容性角度来说建议使用事件冒泡模型。)

2.2.1 冒泡事件流

事件传播顺序是由下至上的,即 某个具体的元素 -> … -> body -> html -> document -> window

在冒泡过程中的任何时候都可以终止事件的冒泡

如果不停止事件的传播,事件将一直通过DOM冒泡直至到达文档根。

  1. 案例
  2. <div id="s1">s1
  3. <div id="s2">s2</div>
  4. </div>
  5. <script>
  6. s1.addEventListener("click",function(e){
  7. console.log("s1 冒泡事件");
  8. },false);
  9. s2.addEventListener("click",function(e){
  10. console.log("s2 冒泡事件");
  11. },false);
  12. </script>

2.2.2 捕获事件流

事件的处理由上往下,即 将从DOM层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递。

在这个过程中,事件会被从文档根到事件目标元素之间各个继承派生的元素所捕获,如果事件监听器在被注册时设置了useCapture属性为true,那么它们可以被分派给这期间的任何元素以对事件做出处理;否则,事件会被接着传递给派生元素路径上的下一元素,直至目标元素。事件到达目标元素后,它会接着通过DOM节点再进行冒泡。

  1. 案例
  2. <div id="s1">s1
  3. <div id="s2">s2</div>
  4. </div>
  5. <script>
  6. s1.addEventListener("click",function(e){
  7. console.log("s1 捕获事件");
  8. },true);
  9. s2.addEventListener("click",function(e){
  10. console.log("s2 捕获事件");
  11. },true);
  12. </script>

2.2.3 addEventListener的第三个参数

w3c 制定了统一的标准——先捕获再冒泡

addEventListener的第三个参数就是为冒泡和捕获准备的

element.addEventListener(event, function, useCapture)

第一个参数是需要绑定的事件
第二个参数是触发事件后要执行的函数
第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。

2.2.4 总结

当事件捕获和事件冒泡一起存在的情况,讨论其如何触发

(记被点击的DOM节点为target节点)

  1. document 往 target节点,捕获前进,遇到注册的捕获事件立即触发执行
  2. 到达target节点,触发事件(对于target节点上,是先捕获还是先冒泡则捕获事件和冒泡事件的注册顺序,先注册先执行)
  3. target节点 往 document 方向,冒泡前进,遇到注册的冒泡事件立即触发

  • 对于非target节点则先执行捕获再执行冒泡(1、3)
  • 对于target节点则是先执行先注册的事件,无论冒泡还是捕获

2.3 DOM事件流模型

三阶段

  • 捕获阶段
  • 目标阶段:真正的目标节点正在处理事件的阶段;
  • 冒泡阶段

2.4 事件委托和事件代理

2.4.1 事件代理

将多个事件处理函数减为一个,而且对于不同的元素可以有不同的处理方法。

【实例】要求点击页面中的li元素,然后输出li当中的颜色

  1. <ul id="color-list">
  2. <li>red</li>
  3. <li>yellow</li>
  4. <li>blue</li>
  5. <li>green</li>
  6. <li>black</li>
  7. <li>white</li>
  8. </ul>
  1. 一般写法(疯狂遍历)
  2. (function(){
  3. var color_list = document.getElementById('color-list');
  4. var colors = color_list.getElementsByTagName('li');
  5. for(var i=0;i<colors.length;i++){
  6. colors[i].addEventListener('click',showColor,false);
  7. };
  8. function showColor(e){
  9. var x = e.target;
  10. console.log("The color is " + x.innerHTML);
  11. };
  12. })();
  1. 利用事件流的特性
  2. (function(){
  3. var color_list = document.getElementById('color-list');
  4. color_list.addEventListener('click',showColor,false);
  5. function showColor(e){
  6. var x = e.target;
  7. if(x.nodeName.toLowerCase() === 'li'){
  8. console.log('The color is ' + x.innerHTML);
  9. }
  10. }
  11. })();

👆只绑定一个事件处理函数也可以完成

2.4.1 事件委托

事件委托以事件冒泡为原理,只指定一个事件处理程序,就可以管理某一类型的所有事件。

事件委托,是将所有的操作放到js程序里面,与dom的操作就只需要交互一次,大大的减少与dom的交互次数,从而提高性能;

适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。

【事件代理和事件委托实际上说的是同一件事,只是站在不同的角度来说的。比如说元素A把事件处理委托给自己的父元素B去处理,那么A就是事件委托方,而B就是事件代理方,两者参与的实际上是同一件事。】

2.5 阻止事件传播

e.stopPropagation()冒泡机制下,阻止事件的进一步往上冒泡。捕获机制下,阻止事件的进一步向下捕获。

e.cancelBubble 是e.stopPropagation() 的曾用名,也可以阻止冒泡和捕获
e.cancelBubble = true;

e.preventDefault()用于取消事件的默认操作,比如链接的跳转或者表单的提交,主要是用来阻止标签的默认行为

return false事件处理过程中,阻止了事件冒泡,也阻止了默认行为

https://www.jb51.net/article/178250.htm

https://www.cnblogs.com/jin-zhe/p/11586327.html

https://zhuanlan.zhihu.com/p/43369093

https://www.kanzhun.com/jiaocheng/333004.html

https://www.jianshu.com/p/cd801d1b3147

https://blog.csdn.net/u014465934/article/details/87915995

https://blog.csdn.net/zhang1600/article/details/11225