浏览器工作原理学习笔记

单进程问题

  • 不稳定,插件崩溃浏览器就崩溃
  • 不流畅,脚本执行会让页面卡顿,内存泄漏也会导致浏览器变慢
  • 不安全,恶意插件和恶意脚本容易获取系统权限作恶

多进程优点

  • 进程隔离,插件或者页面崩溃不会导致其他页面崩溃
  • 页面隔离,即使 js 阻塞了渲染进程,影响到的也只是当前的渲染页面,而并不会影响浏览器和其他页面,其他页面的脚本是运行在它们自己的渲染进程中的,浏览器也可以正常使用。
  • 通过安全沙盒解决安全问题

五个常见进程

rel="noopener noreferrer"

浏览器渲染机制

  • DOM:渲染引擎解析 html 文档,构建 DOM Tree
  • Computed Style:解析对应的 css 样式信息,生成 document.styleSheets,计算 DOM 样式
  • 布局(reflow/layout):计算布局信息,生成布局树 LayoutTree
  • 分层(layer):对布局树进行分层。满足以下条件之一就会提升为单独图层:有层叠上下文属性,或者需要裁剪(超出/滚动)。
  • 绘制(repaint/paint):遍历渲染树,绘制每个节点,把每一个元素对应的盒变成位图。 

重排、重绘、合成

  • 重排(reflow):当渲染树中的部分因为元素的尺寸、布局、隐藏等改变而需要重新构建。触发条件:页面渲染初始化(无法避免)、添加或删除 DOM、DOM 位置或尺寸的改变、浏览器窗口尺寸的变化、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变。
  • 重绘(repaint):改变元素外观所触发的行为,浏览器会根据元素的新属性重新绘制,省去了布局和分层阶段。比如,仅修改 DOM 元素的字体颜色。
  • 合成:既不改布局也不需要绘制,比如 css transform 动画,避开重排与重绘阶段,在非主线程上执行合成动画操作。
  • display: none; 会发生 reflow,而 visibility: hidden; 只会触发 repaint

如何避免重排重绘

  • 通过 class 批量修改样式
  • 使用离线 DOM 或者 documentFragment
  • 避免使用 table 布局
  • 对类似 window resize 这样的事件做 debounce
  • 对 dom 属性的读写分离

js 和 CSS 阻塞

  • JS:会先下载并执行,再继续渲染,也就是说,下载和执行,都会阻塞 DOM 解析,因为 JS 可能存在 DOM 操作
  • CSS:正常不会阻塞 DOM 解析,但是遇到 script 标签会触发渲染,会等到 CSS 下载完成再继续执行,这种情况下会阻塞 DOM 解析。

五个常驻线程

JS Runtime 是单线程,但是浏览器提供多线程环境

  • GUI 渲染线程:负责解析html,CSS,构建DOM树,布局和绘制,与 JS 引擎线程互斥
  • JS 引擎线程:负责处理 JS 脚本,执行会阻塞渲染线程
  • 定时器触发线程:负责执行定时器一类函数的进程,如 setTimeout、setInterval。主线程执行代码遇到计时器时,会将计时器交给该线程处理,当计时完毕之后,定时器线程会将计时完毕后的事件加入到事件队列的尾部,等待 JS 引擎线程的执行
  • 事件触发线程:主要负责将准备好执行的事件交给 JS 引擎线程执行,如计时器计时完毕后的事件,AJAX 请求成功返回并触发的回调函数和用户触发点击事件时,事件触发线程会将回调函数加入到任务队列的尾部,等待 JS 引擎线程的执行
  • 异步 HTTP 请求线程:当主线程依次执行代码时,遇到异步请求,会将函数交给改线程处理,当监听状态码变更时,如果有回调函数,会将回调函数加入到任务队列的尾部,等待 JS 引擎线程的执行

豌豆资源搜索网站https://55wd.com 广州vi设计公司http://www.maiqicn.com

Event Loop

主线程从任务队列读取事件这个过程,是循环不断的,称之为 Event Loop。

  • 执行栈里清空了,才会从任务队列中取任务,浏览器不止一个任务队列(Task Queue 和 Microtask Queue)
  • setTimeout 是浏览器行为,和 DOM 事件一样
  • 宏观任务一个一个执行,微任务一批一批执行

异步任务有两种:

  • 宏任务(Macrotask):宿主发起的任务,包括整体代码 script,setTimeout,setInterval、setImmediate、I/O操作、UI rendering
  • 微任务(Microtask):JavaScript 引擎发起的任务,process.nextTick, Promises, Object.observe, MutationObserver

 

事件模型

DOM 事件模型分为捕获和冒泡。一个事件发生后,会在子元素和父元素之间传播(propagation)。

这种传播分成三个阶段:

  • 捕获阶段:事件从 window 对象自上而下向目标节点传播的阶段
  • 目标阶段:真正的目标节点正在处理事件的阶段
  • 冒泡阶段:事件从目标节点自下而上向 window 对象传播的阶段

在实际监听事件时,可以这样使用冒泡和捕获机制:默认使用冒泡模式;当开发组件时,遇到需要父元素控制子元素的行为,可以使用捕获机制。

豌豆资源搜索网站https://55wd.com 广州vi设计公司http://www.maiqicn.com

事件代理

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,通过 event.target 来判断。这种方法叫做事件的代理(delegation)。

优点:

    • 减少内存消耗,提高性能
    • 方便动态绑定事件
原文地址:https://www.cnblogs.com/qianxiaox/p/13740309.html