前端学习笔记(给自己看)

207 阅读7分钟

浏览器页面打开流程

用户输入URL

beforeunload事件触发


浏览器进程提交URL请求给网络进程

http,https,dns,缓存,cookie

content-type

如果是下载类型的contentType,会提交下载任务到下载管理器,同时导航事件结束(不会跳转?)

准备渲染进程

same-site

同协议+相同的顶级域名

但跨域的验证更为严格:同协议+同域名+同端口

从当前页面打开一个一个samesite会复用当前页面的渲染进程(经验证无效)

提交渲染

浏览器进程接收到网络进程提交的响应头

如果是text/html

  • 向渲染进程发送提交文档的消息,

  • 渲染进程收到消息之后与网络进程建立管道接受数据,

  • 文档传输完毕之后,渲染进程提交确认提交消息,

  • 浏览器收到确认提交消息之后,更新界面状态:清空页面,更新地址栏,更新前进后退状态(history?)

img

如果不是text/html,如下载类型,则提交到下载管理器,结束导航

渲染

提交文档之后,渲染进程开始渲染

渲染完毕之后,通知浏览器进程,浏览器进程停止转圈

其他:

  • 用户发出 URL 请求到页面开始解析的这个过程,就叫做导航
  • 新页面的渲染发生在导航之后

渲染流程

img

输入 ---- > 处理 ----> 输出

构建DOM树

作用:

​ 将html语法编译成浏览器能够理解的结构

DOM树的构建流程:

img

解析过程中使用的数据结构:

  • 栈:解析 html语法
  • 树:保存 DOM 树 数据结构

DOM树 和 HTML 的 区别:

结构基本相同,DOM树保存在内存中,可通过代码增删改查;通过HTML生成DOM树

样式计算

生成styleSheets

作用: 将CSS转换成浏览器能够理解的结构

来源:

  • style标签

  • link链接 ref="stylesheet"

  • 节点的内联样式

    img

产物:

​ 生成styleSheets(documen.styleSheets),具备查询和修改的功能(不可增删??)

标准化

  • 哪些是标准值?

img

DOM样式计算:生成ComputedStyle

生成产物:

​ ComputedStyle:每个DOM节点最后生效的CSS配置以及被覆盖的CSS配置,控制台中查看

img

布局阶段: 构建布局树

有了DOM树 + ComputedStyle , 下一步:开始计算每个元素应该放在哪个位置

  • 构建布局树(排除掉DOM中的不可见元素 ;display:none,head标签,css标签,script标签)

    img

分层:生成图层树

构建图层树

  • 拥有层叠上下文属性的元素会被提升为单独的一层
  • 需要剪裁(clip)的地方也会被创建为图层。overflow:scroll

img

绘制:根据视口栅格化每个图层

绘制每一个图层。

通过开发者工具,layers查看页面的图层

img

​ 区域 1 就是 document 的绘制列表,拖动区域 2 中的进度条可以重现列表的绘制过程

img

  • DOM:生成DOM树

  • Style:CSS语法解析,生成ComputedStyle

  • Layout:排列元素

  • Layer:元素分层

  • Paint:生成绘制(命令)列表

    视口

    用户可见区域

    img

    分块:根据选择需要合成的图块

视口很小,但是图层的面积可能很大,需要对图层进行分块来减小绘制区域

img

栅格化:合成位图

所以:栅格化就是将图块合成为位图的过程。栅格化一般由GPU来完成

合成 + 显示

  1. 将分块的图块合成为一个位图

  2. 通知浏览器进程,合成所有图层的位图,显示到显示器。

img
  • tiles:图块
  • raster:光栅化
  • drawguad:命令:通知浏览器进程去GPU那边读取数据显示到显示器上

完整流程:

  1. 渲染进程将 HTML 内容转换为能够读懂的 DOM 树结构。
  2. 渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets,计算出 DOM 节点的样式。
  3. 创建布局树,并计算元素的布局信息。
  4. 对布局树进行分层,并生成分层树(图层)。
  5. 为每个图层生成绘制列表,并将其提交到合成线程。
  6. 合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。
  7. 合成线程发送绘制图块命令 DrawQuad 给浏览器进程。浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。

其他

重排(重新布局):主线程

  • 重排的花销跟render tree有多少节点需要新构建有关系,假如在body最前面插入一个元素,会导致整个render tree回流,但如果是指body后面插入一个元素,则不会影响前面的元素重排。

  • 当页面布局和几何属性改变时就需要重排。

img

重绘:主线程

img

直接合成:非主线程

规定:transform 不会改变元素的布局

img

JS,CSS对DOM解析的影响

CSS
  1. CSS 不会阻塞DOM的解析,但是会阻塞DOM的渲染
  2. CSS 会阻塞定义在其后的JS的执行
  3. 虽然CSS不会阻塞DOM的解析,但是JS会,所以如果CSS后面如果还有JS(非async,defer),这种情况下CSS简介的阻塞了DOM的解析
JS
  1. JS 会阻塞DOM的解析
  2. 动态插入的脚本不会阻塞页面解析,并在加载完成之后立即执行;可以设置script.async = false,设置为按照defer模式的顺序执行
  3. img
  4. defer 和 async 都只能用于外部脚本,如果 script 没有 src 属性,则会忽略它们。
  5. defer ,async: 并行下载;
  6. 多个 defer 的脚本执行顺序严格按照定义顺序进行,而不是先下载好的先执行;
  7. 多个 async,按照谁先下载完成谁先执行的原则进行,所以当它们之间有顺序依赖的时候特别容易出错。
  8. defer 脚本下载完成后,执行时间一定是 DOMContentLoaded 事件触发之前执行;
  9. async 脚本的执行 和 DOMContentLoaded 的触发顺序无法明确谁先谁后,因为脚本可能在 DOM 构建完成时还没下载完,也可能早就下载好了;

事件循环


JS执行机制(删)

编译阶段

创建执行上下文

有三种情况下执行JS代码会创建上下文

  • 执行、加载一个JS模块(文件):
    • 会编译全局代码(最外层的代码,不在其他上下文中的代码)
    • 并创建全局执行上下文(唯一)
    • 页面销毁时清除上下文
  • 调用一个函数:
    • 编译函数体内的代码,
      • 函数调用时才会被编译
    • 创建函数执行上下文
    • 函数退出后清除上下文
  • eval:
    • 调用eval时编译代码,
    • 创建eval上下文
  • class
    • class的上下文为class实例对象

执行阶段

调用栈(执行上下文栈)

比Java中的调用栈复杂,Java没有上下文栈这中概念,Java中万物皆对象(class),this,就是当前对象

Java的调用栈只保存方法的局部变量

img

console.trace() 输出调用栈

变量环境

通过 var ,function 声明;声明的对象会被保存在最近的上下文环境中

词法环境

通过let,const 声明;声明的对象会被保存在最近的词法环境中

能生成上下文环境的都可以生成词法环境,方法块也可以生成词法环境

var的创建和初始化被提升,赋值不会被提升。 let的创建被提升,初始化和赋值不会被提升。 function的创建、初始化和赋值均会被提升。

Temporal Dead Zone,指的是从block创建到初始化完成之间的时间

在初始化之前使用对象会引发:

Uncaught ReferenceError: Cannot access 'myname' before initialization

作用域链:JavaScript 语言的作用域链是由词法作用域决定的,而词法作用域是由代码结构来确定的。

img

作用域链和 this 是两套不同的系统,它们之间基本没太多联系

使用对象来调用其内部的一个方法,该方法的 this 是指向对象本身的