Vue3源码解析

110 阅读4分钟

Vue3优化点

源码优化

使用monorepo和TS管理和开发源码,提升自身代码可维护性 monorepo把模块拆分到不同的package中,每个package有各自的APi、类型定义和测试。模块拆分更细化,职责划分更明确,模块之间的依赖关系更明确。

vue2中使用的是flow,但是flow对于复杂数据类型的检测不友好,不能检测到propOptions的类型

性能优化

引入treee-shaking的技术,依赖ES6模块语法的静态结构(import /export),通过编译阶段的静态分析,找到没有引入的模块并打上标记。

项目中没有引入的组件,打包后就不会引入组件,间接减少项目的体积

数据劫持优化

object.defineProperty劫持数据的getter和setter,但这个API有缺陷,必须知道要拦截的Key是什么,不能检测对象的添加和删除,虽然vue中提供了setset和delete实力方法。

对于嵌套层级比较深的对象,需要递归遍历对象,把每一层的数据都变成响应式的,增加了性能负担

Proxy API做数据劫持,getter和setter方法,是劫持整个对象,对对象的增加和删除都能检测到。

注意:proxy API 并不能监听到内部深层次的对象变化,vue3中处理方式是在getter中去递归响应式。【好处是:只有在真正访问到的内部对象才会变成响应式】

编译优化--- diff

通过编译阶段对静态模版的分析,编译生成Block tree

Block tree是将一个模版基于动态节点指令切割的嵌套区块,每个区块内部的节点结构是固定的,每个区块只需要一个Array追踪自身包含的动态节点。

借助Block tree,vue.js将vnode更新性能由与模版整体大小相关提升为与动态内容的数量相关

编译阶段还包含了对slot的编译优化,事件监听函数的缓存优化,运行时重写了diff算法

语法优化--composition API

options API是按照methods\computed\data\props不同的选项分类的。在大型组件中,一个组件会有很多个处理逻辑点,不友好

composition API 需要修改的都在一个函数中,方便

优化逻辑复用

vue2中mixins,会出现命名冲突和数据来源不清晰的情况

mixins会定义props、data时会出现相同的变量,导致命名冲突

composition API 在逻辑复用有优势,也提供类型支持。在调用函数时,所有的类型被推导出来,不会像o ptions API,使用this

vnode到真实的DOM渲染过程

创建vnode----渲染vnode---生成DOM

入口文件

createApp:

const createApp = ((...args)=>{
  // 创建app对象
  const app = ensureRenderer().createApp(...args)
  const {mount} = app
  // 重写mount方法
  app.mount = (containerOrSelector) => {
    ...
  }
  return app
})

ensureRender()用来创建一个渲染器对象:

源码核心模块

Vue.js 的核心思想可以概括为以下几点:

  1. 响应式数据绑定:Vue.js 通过数据劫持和依赖追踪技术,实现了数据的双向绑定,使得数据和视图之间能够保持实时同步。
  2. 组件化构建:Vue.js 采用组件化思想,将页面拆分为多个独立的组件,提高了代码的可维护性和复用性。
  3. 虚拟 DOM:Vue.js 通过虚拟 DOM 技术,减少了对真实 DOM 的操作,提高了页面的渲染性能。

所有的目录中最核心的就是packages 目录 , Vue3 的源码存放在此目录中:

  • compiler-core: 编译解析核心,与具体环境无关,主要生成AST, 并根据AST生成render()方法
  • compiler-dom: 浏览器环境中模板解析逻辑, 如处理HTML转义, 处理v-model等指令
  • compiler-sfc: 负责解析Vue单文件组件
  • compiler-ssr: 服务端渲染环境中的模板解析逻辑
  • reactivity: 响应式数据相关逻辑,Proxy 就在这里面
  • runtime-core: 运行时与创建实例相关代码
  • runtime-dom: 浏览器环境中的运行时核心
  • runtime-test: 内部测试代码
  • server-renderer: 用于SSR服务端渲染的逻辑
  • shared: Vue3 工具库,一些通用方法
  • size-check: 用于测试tree shaking 后代码大小的示例库
  • template-explorer: 用于检查模板编译后的输出, 主要用于开发调试
  • vue: Vue3 主入口文件,包括运行时和 编译器

 最重要源码模块

通过目录名称我们可以看到package中最重要的模块有5个, 分别为

  1. compiler-core :编译
  2. compiler-dom
  3. runtime-core:运行
  4. runtime-dome
  5. reactivity:响应式