Web应用的生命周期概览
以下是Web应用的生命周期的大致流程:
- 生命周期开始:用户通过网址打开并访问网页
- 浏览器(客户端)生成请求并发送至服务器
- 服务器依据请求获取某些资源并返回响应给客户端
- 页面构建:浏览器收到服务器发来的资源(html文件、css文件、js文件、图片、数据等…),开始处理并渲染这些资源
- 事件处理:生成了一个事件队列,一次只处理队列中的一个事件
- 用户动作:与页面交互(点击、键盘输入等… ),生成的事件进入事件队列等待执行
- 生命周期结束:用户关闭web页面
在生命周期进行的过程中,除了生命周期的开始与结束,其他步骤都会在用户与页面的交互中重复执行,其中需要重点关注的两个阶段是:页面构建以及事件处理
页面构建阶段
页面构建阶段主要的目标是建立web应用的UI,其主要包括两个步骤:
-
解析HTML代码并构建文档对象(DOM) 步骤1会在浏览器处理HTML节点的过程中执行,该过程的两个重要内容:HTML解析和DOM构建 -
执行JavaScript代码 步骤2会在HTML解析到脚本节点(包含或引用JavaScript代码的节点)时执行,该步骤会暂时打断步骤1的执行
在页面的构建阶段中,以上两个步骤会交替执行多次,接下来是进一步的介绍:
HTML解析和DOM构建
DOM是根据HTML来创建的,两者紧密联系,但需要强调的是:DOM并不等同于HTML
可以把HTML代码看作是浏览器构建DOM的参考图,在依据这个参考图构建DOM的过程中,浏览器会默默的修复参考图中的一些问题,所以有时候会出现实际浏览器生成的DOM结构与HTML代码并不是完全一样的情况
举个例子,下面是一段结构奇怪的html代码:
<html>
<head>
<p>hello~</p>
</head>
<body>
<p>
hi~
<div>ooh~</div>
</p>
</body>
</html>
上面的代码尝试把<p> 放入<head> 中,把<div> 包含在<p> 中,然而代码实际在浏览器中渲染出的结构是这样的:
通过对比可以看出,所构建出的实际DOM结构与HTML代码并完全不一样,这里就体现出了上面提到的DOM修复HTML代码的功能,浏览器把HTML代码中逻辑不正确的地方渲染成了符合语法逻辑的DOM结构。当然,这就造成了页面出现了与代码不一致的效果,所以在编写代码时要避免这种奇怪的代码结构,以防出现一些意料之外的效果
执行JavaScript代码
每当解析到脚本元素时,浏览器就会停止从HTML构建DOM,并开始执行JavaScript代码,着重关注以下两点:
浏览器暴露给JavaScript引擎的主要是全局的window对象,其中最重要的属性就是document对象,它代表了当前页面的DOM
在执行JavaScript代码时,会涉及到对已经构建好的DOM节点的操作(插入、修改、删除DOM节点等…),要操作DOM节点,前提就是该DOM节点已经被浏览器构建好了,不可能去操作还没有存在的节点,这就是为什么要把<script> 标签放在整个代码底部或者在JavaScript代码中window.onload() 下执行的原因,为的就是在DOM节点已经构建好后再对DOM节点进行操作
JavaScript代码执行过程中还涉及到了注册事件监听器的操作,这关系到下个步骤的事件处理阶段
在当前脚本文件执行结束后会继续构建DOM,直到浏览器处理完所有的HTML元素,整个页面构建阶段才算完成,接下来会进入事件处理阶段
插播一个小知识:script 标签的三种运行机制
<script src="xxx.js"></script>
<script src="xxx.js" defer></script>
<script src="xxx.js" async></script>
事件处理阶段
浏览器执行的模式为单线程模式:同一时刻只能执行一个代码片段
浏览器处理事件的方式:事件队列
下面是简单的事件处理的逻辑流程图:(流程图的右半部分是一个事件循环模型)
这里需要明确的一个观点是事件是异步的,产生事件并加入到事件队列这个过程对于事件循环是分开的,即上图的左半边和右半边是两个独立的过程
上述的事件处理的逻辑会一直持续,直到用户关闭了web应用,整个事件处理阶段才会结束
参考:《JavaScript忍者秘籍》
|