Vue源碼學習一

Vue

程序結構

此處輸入圖片的描述
Vue.js 是一個非常典型的 MVVM 的程序結構,整個程序從最上層大概分爲

全局設計:包括全局接口、默認選項等
vm 實例設計:包括接口設計 (vm 原型)、實例初始化過程設計 (vm 構造函數)
這裏面大部分內容可以直接跟 Vue.js 的官方 API 參考文檔對應起來,但文檔裏面沒有且值得一提的是構造函數的設計,下面是我摘出的構造函數最核心的工作內容

此處輸入圖片的描述
整個實例初始化的過程中,重中之重就是把數據 (Model) 和視圖 (View) 建立起關聯關係。Vue.js 和諸多 MVVM 的思路是類似的,主要做了三件事:

  • 通過 observer 對 data 進行了監聽,並且提供訂閱某個數據項的變化的能力
  • 把 template 解析成一段 document fragment,然後解析其中的 directive,得到每一個 directive 所依賴的數據項及其更新方法。比如 v-text=”message” 被解析之後 (這裏僅作示意,實際程序邏輯會更嚴謹而複雜)
  • 通過 watcher 把上述兩部分結合起來,即把 directive 中的數據依賴訂閱在對應數據的 observer 上,這樣當數據變化的時候,就會觸發 observer,進而觸發相關依賴對應的視圖更新方法,最後達到模板原本的關聯效果。

所以整個 vm 的核心,就是如何實現 observer, directive (parser), watcher 這三樣東西

編譯流程

此處輸入圖片的描述

模板解析過程

相關源碼
將template解析爲AST(抽象語法樹)

AST

  • 節點類型有三種: ASTElement:tag標籤、ASTText:純文本、ASTExpression: 表達式
  • eg:
declare type ASTNode = ASTElement | ASTText | ASTExpression;

declare type ASTElement = {
  type: 1;
  tag: string;
  attrsList: Array<{ name: string; value: string }>;
  attrsMap: { [key: string]: string | null };
  parent: ASTElement | void;
  children: Array<ASTNode>;
  static?: boolean; // 靜態節點標記
  ……
}

此處輸入圖片的描述

compile() 函數

再來看 compile() 函數,這裏是實現模板解析的核心,來做文件 src/compiler/index.js,基本邏輯爲:

 // 參數:template, options
ast = parse(template.trim(), options)
optimize(ast, options)
code = generate(ast, options)
return {
  ast,
  render: code.render,
  staticRenderFns: code.staticRenderFns
}

邏輯很清晰,首先從模板進行解析得到抽象語法樹(ast),進行優化,最後生成結果代碼。整個過程中肯定會涉及到 Vue 的語法,包括指令、組件嵌套等等,不僅僅是得到構建 Virtual DOM 的代碼。

需要注意的是,編譯得到 render 其實是代碼文本,通過 new Function(code) 的方式轉爲函數

Vue數據綁定圖解

此處輸入圖片的描述

diff

參考Vue原理解析之Virtual Dom

Vue運行機制小結

  • 文本模板,編譯得到生成 vnode 的函數(render),該過程中會識別並記錄 Vue 的指令和其他語法
  • new Vue() 得到 vm 對象,其中傳入的數據會進行數據劫持處理,從而可以收集依賴,實現數據綁定
  • 渲染過程是將所有數據交由渲染函數(render)進行調用得到 vnode,應該 Virtual DOM 的機制實現初始渲染和更新
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章