Vue 3 源碼導讀

5號凌晨,尤雨溪公佈了 Vue 3 源代碼javascript

話很少說,咱們趁熱對 Vue 3 源碼進行一些簡要的分析。vue

若是你尚未閱讀過 Composition API RFC,可能沒法徹底看懂下面的內容。java

兼容性

目前打包後的代碼是 ES2015+,不支持 IE 11。node

對 TypeScript 的使用

目前的代碼 98% 以上使用 TypeScript 編寫。react

若是你尚未學習 TypeScript,請儘快學習,不然可能看不懂源碼。git

另外有件事情說出來可能會讓你很是驚訝,Vue 3 的源代碼徹底沒有使用 class 關鍵字!(只在測試代碼和示例代碼裏用到了 class 關鍵字)github

何時發正式版

目前 Vue 3 處於 Pre-Alpha 版本。後面應該還會有 Alpha、Beta 等版本。api

根據 Vue 官方時間表,至少要等到 2020 年第一季度纔有可能發佈 3.0 正式版。瀏覽器

閱讀建議

強烈推薦你們用國慶假期這段時間把 Vue 3 的源碼通看一遍,由於目前的代碼結構清晰,並且代碼量相對較少。app

下載代碼後,使用 yarn dev 命令就能夠對其進行調試。(有人給出了詳細的調試技巧)

關於閱讀順序,個人建議是

  1. 先讀 reactivity,能最快了解 Vue 3 的新特性;
  2. 再讀 rumtime,理解組件和生命週期的實現;
  3. 若是還有時間再讀 compiler,理解編譯優化過程。

另外若是你想省時間,能夠直接看全部 __tests__ 目錄裏的測試用例來了解 Vue 3 的全部功能。目前有不到 700 個測試用例。

代碼結構

代碼倉庫中有個 packages 目錄,裏面是 Vue 3 的主要功能的實現,包括

  • reactivity 目錄:數據響應式系統,這是一個單獨的系統,能夠與任何框架配合使用。
  • runtime-core 目錄:與平臺無關的運行時。其實現的功能有虛擬 DOM 渲染器、Vue 組件和 Vue 的各類API,咱們能夠利用這個 runtime 實現針對某個具體平臺的高階 runtime,好比自定義渲染器。
  • runtime-dom 目錄: 針對瀏覽器的 runtime。其功能包括處理原生 DOM API、DOM 事件和 DOM 屬性等。
  • runtime-test 目錄: 一個專門爲了測試而寫的輕量級 runtime。因爲這個 rumtime 「渲染」出的 DOM 樹實際上是一個 JS 對象,因此這個 runtime 能夠用在全部 JS 環境裏。你能夠用它來測試渲染是否正確。它還能夠用於序列化 DOM、觸發 DOM 事件,以及記錄某次更新中的 DOM 操做。
  • server-renderer 目錄: 用於 SSR。還沒有實現。
  • compiler-core 目錄: 平臺無關的編譯器. 它既包含可擴展的基礎功能,也包含全部平臺無關的插件。
  • compiler-dom 目錄: 針對瀏覽器而寫的編譯器。
  • shared 目錄: 沒有暴露任何 API,主要包含了一些平臺無關的內部幫助方法。
  • vue 目錄: 用於構建「完整構建」版本,引用了上面提到的 runtime 和 compiler。

能夠看出,新的 Vue 代碼倉庫是模塊化的。接下來咱們逐一來看看每一個模塊暴露的 API。

@vue/runtime-core 模塊

大部分 Vue 開發者應該不會用到這個模塊,由於它是專門用於自定義 renderer 的。

使用方法示例:

import { createRenderer, createAppAPI } from '@vue/runtime-core'

const { render, createApp } = createRenderer({
  pathcProp,
  insert,
  remove,
  createElement,
  // ...
})

// `render` 是底層 API
// `createApp` 會產生一個 app 實例,該實例擁有全局的可配置上下文
export { render, createApp }

export * from '@vue/runtime-core'
複製代碼

@vue/runtime-dom 模塊

這個模塊是基於上面模塊而寫的瀏覽器上的 runtime,主要功能是適配了瀏覽器環境下節點和節點屬性的增刪改查。它暴露了兩個重要 API:render 和 createApp,並聲明瞭一個 ComponentPublicInstance 接口。

export { render, createApp }

// re-export everything from core
// h, Component, reactivity API, nextTick, flags & types
export * from '@vue/runtime-core'

export interface ComponentPublicInstance {
  $el: Element
}
複製代碼

@vue/runtime-test 模塊

這個模塊的主要功能是用對象來表示 DOM 樹,方便測試。而且提供了不少有用的 API 方便測試:

export { render, createApp }

// convenience for one-off render validations
export function renderToString(vnode: VNode) {
  const root = nodeOps.createElement('div')
  render(vnode, root)
  return serializeInner(root)
}

export * from './triggerEvent'
export * from './serialize'
export * from './nodeOps'
export * from './jestUtils'
export * from '@vue/runtime-core'
複製代碼

@vue/reactivity 模塊

這是一個極其重要的模塊,它是一個數據響應式系統。其暴露的主要 API 有 ref(數據容器)、reactive(基於 Proxy 實現的響應式數據)、computed(計算數據)、effect(反作用) 等幾部分:

export { ref, isRef, toRefs, Ref, UnwrapRef } from './ref'
export {
  reactive,
  isReactive,
  readonly,
  isReadonly,
  toRaw,
  markReadonly,
  markNonReactive
} from './reactive'
export {
  computed,
  ComputedRef,
  WritableComputedRef,
  WritableComputedOptions
} from './computed'
export {
  effect,
  stop,
  pauseTracking,
  resumeTracking,
  ITERATE_KEY,
  ReactiveEffect,
  ReactiveEffectOptions,
  DebuggerEvent
} from './effect'
export { lock, unlock } from './lock'
export { OperationTypes } from './operations'
複製代碼

很明顯,這個模塊就是 Composition API 的核心了,其中的 ref 和 reactive 應該重點掌握。

@vue/compiler-core 模塊

這個編譯器的暴露了 AST 和 baseCompile 相關的 API,它能把一個字符串變成一棵 AST。

export function baseCompile( template: string | RootNode, options: CompilerOptions = {} ): CodegenResult {
  // 詳情略 ...
  return generate(ast, options)
}

export { parse, ParserOptions, TextModes } from './parse'
export { transform /* ... */ } from './transform'
export { generate, CodegenOptions, CodegenContext, CodegenResult} from './codegen'
export { ErrorCodes, CompilerError, createCompilerError } from './errors'
export * from './ast'
複製代碼

@vue/compiler-dom 模塊

這個模塊則基於上個模塊,針對瀏覽器作了適配,如對 textarea 和 style 標籤作了特殊處理。

@vue/server-renderer 模塊

目前這個模塊沒有實現任何功能。

vue 模塊

這個模塊就是簡單的引入了 runtime 和 compiler:

import { compile, CompilerOptions } from '@vue/compiler-dom'
import { registerRuntimeCompiler, RenderFunction } from '@vue/runtime-dom'

function compileToFunction( template: string, options?: CompilerOptions ): RenderFunction {
  const { code } = compile(template, {
    hoistStatic: true,
    ...options
  })
  return new Function(code)() as RenderFunction
}

registerRuntimeCompiler(compileToFunction)

export { compileToFunction as compile }
export * from '@vue/runtime-dom'
複製代碼

關注我

關注我,若是 Vue 3 有任何新消息,我會第一時間給出分析。

完。

相關文章
相關標籤/搜索