文章目錄 一、Vue 核心架構設計 二、響應式系統源碼解析 三、虛擬DOM與Diff算法實現 3.1 Diff算法流程圖 3.2 核心Diff源碼 四、模板編譯全流程剖析 五、組件系統與生命周期 六、異步更新隊列與性能優化 七、Vue 3 新特性源碼對比 八、手寫迷你Vue框架實戰 總結
一、Vue 核心架構設計
1.1 整體架構流程圖
模板/JSX
編譯器
渲染函數
虛擬DOM樹
Patch算法
真實DOM
數據響應系統
依賴收集
派發更新
1.2 模塊職責劃分
模塊 源碼文件 核心職責 響應式系統 src/core/observer 數據劫持/依賴管理 虛擬DOM src/core/vdom VNode創建/Diff/Patch 編譯器 src/compiler 模板轉渲染函數 組件系統 src/core/instance 組件實例生命周期管理
二、響應式系統源碼解析
2.1 核心類關系圖
Observer
+walk(data)
+defineReactive()
Dep
+subs: Watcher[]
+depend()
+notify()
Watcher
+get()
+update()
2.2 核心源碼分析
2.2.1 數據劫持實現
export class Observer { constructor ( value ) { this . value = valuethis . dep = new Dep ( ) def ( value, '__ob__' , this ) if ( Array. isArray ( value) ) { this . observeArray ( value) } else { this . walk ( value) } } walk ( obj ) { const keys = Object. keys ( obj) for ( let i = 0 ; i < keys. length; i++ ) { defineReactive ( obj, keys[ i] ) } }
} function defineReactive ( obj, key ) { const dep = new Dep ( ) let val = obj[ key] Object. defineProperty ( obj, key, { enumerable : true , configurable : true , get : function reactiveGetter ( ) { if ( Dep. target) { dep. depend ( ) } return val} , set : function reactiveSetter ( newVal ) { if ( newVal === val) return val = newValdep. notify ( ) } } )
}
2.2.2 依賴收集過程
let uid = 0
export default class Dep { static target = null constructor ( ) { this . id = uid++ this . subs = [ ] } depend ( ) { if ( Dep. target) { Dep. target. addDep ( this ) } } notify ( ) { const subs = this . subs. slice ( ) for ( let i = 0 ; i < subs. length; i++ ) { subs[ i] . update ( ) } }
}
三、虛擬DOM與Diff算法實現
3.1 Diff算法流程圖
Yes
No
Yes
No
Yes
No
新舊VNode對比
相同節點?
更新屬性
替換節點
有子節點?
執行子節點Diff
流程結束
雙指針遍歷
找到可復用節點?
移動節點
新建節點
3.2 核心Diff源碼
function updateChildren ( parentElm, oldCh, newCh ) { let oldStartIdx = 0 let newStartIdx = 0 let oldEndIdx = oldCh. length - 1 let newEndIdx = newCh. length - 1 while ( oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) { if ( sameVnode ( oldStartVnode, newStartVnode) ) { patchVnode ( ... ) oldStartIdx++ newStartIdx++ } } if ( oldStartIdx > oldEndIdx) { addVnodes ( ... ) } else if ( newStartIdx > newEndIdx) { removeVnodes ( ... ) }
}
四、模板編譯全流程剖析
4.1 編譯流程圖
Template AST Render 解析器生成抽象語法樹 優化器標記靜態節點 代碼生成器輸出渲染函數 Template AST Render
4.2 編譯階段源碼
export function compileToFunctions ( template ) { const ast = parse ( template. trim ( ) ) optimize ( ast) const code = generate ( ast) return { render : new Function ( code. render) , staticRenderFns : code. staticRenderFns. map ( fn => new Function ( fn) ) }
}
function render ( ) { with ( this ) { return _c ( 'div' , { attrs : { "id" : "app" } } , [ _c ( 'p' , [ _v ( _s ( message) ) ] ) , _c ( 'button' , { on : { "click" : handleClick} } , [ _v ( "Click" ) ] ) ] ) }
}
五、組件系統與生命周期
5.1 組件初始化流程
initMixin VueComponent patch 合并選項 初始化生命周期 初始化事件 初始化渲染 創建$el initMixin VueComponent patch
5.2 生命周期源碼觸發點
Vue . prototype. _init = function ( options ) { initLifecycle ( vm) initEvents ( vm) initRender ( vm) callHook ( vm, 'beforeCreate' ) initInjections ( vm) initState ( vm) initProvide ( vm) callHook ( vm, 'created' ) if ( vm. $options. el) { vm. $mount ( vm. $options. el) }
}
六、異步更新隊列與性能優化
6.1 更新隊列流程圖
數據變更
觸發setter
將Watcher推入隊列
nextTick后執行
執行Watcher.run
觸發組件更新
6.2 核心實現代碼
const queue = [ ]
let waiting = false function flushSchedulerQueue ( ) { queue. sort ( ( a, b ) => a. id - b. id) for ( let i = 0 ; i < queue. length; i++ ) { const watcher = queue[ i] watcher. run ( ) } resetSchedulerState ( )
} export function queueWatcher ( watcher ) { if ( ! queue. includes ( watcher) ) { queue. push ( watcher) } if ( ! waiting) { nextTick ( flushSchedulerQueue) waiting = true }
}
七、Vue 3 新特性源碼對比
7.1 響應式系統升級
function reactive ( target ) { return new Proxy ( target, { get ( target, key, receiver) { track ( target, key) return Reflect. get ( ... arguments) } , set ( target, key, value, receiver) { Reflect. set ( ... arguments) trigger ( target, key) } } )
}
7.2 編譯優化對比
優化點 Vue 2 Vue 3 靜態提升 無 標記靜態節點 補丁標志 全量Diff 動態節點追蹤 緩存事件 每次渲染重新創建 緩存事件處理函數
八、手寫迷你Vue框架實戰
8.1 核心實現代碼
class MyVue { constructor ( options ) { this . $options = optionsthis . _data = options. data ( ) new Observer ( this . _data) new Compiler ( options. el, this ) }
} class Observer { constructor ( data ) { this . walk ( data) } walk ( data ) { Object. keys ( data) . forEach ( key => { defineReactive ( data, key, data[ key] ) } ) }
} function defineReactive ( obj, key, val ) { const dep = new Dep ( ) Object. defineProperty ( obj, key, { get ( ) { Dep. target && dep. addSub ( Dep. target) return val} , set ( newVal) { val = newValdep. notify ( ) } } )
}
總結
本文從Vue源碼層面深入解析了響應式系統、虛擬DOM、模板編譯等核心模塊的實現原理。建議通過以下方式進一步學習:
使用Vue官方調試版本進行斷點調試 參與Vue源碼GitHub Issue討論 對比不同版本實現差異