前言
時隔半年,再寫一篇關于vue源碼的總結文章,期間剛好工作了半年(也剛好用了半年vue),也陸陸續續地看了一些別人寫的源碼分析。這里再記下對vue的認識。
vue 框架運行的三個重要階段
- 配置項校驗合并階段
參見Vue源碼分析(3)--選項合并過程mergeOptions - 初始化響應式系統
參見Vue源碼分析(4)--實例的初始化過程 - 組件掛載、依賴收集、頁面更新(Virtual DOM Diff)
參見Vue源碼分析(5)--觀察者收集、組件渲染掛載過程
vue 框架的三大核心內容
- 響應式系統
data中的對象obj會被觀測(observe),結果就是obj的每個可枚舉屬性都被配置了一個dep屬性,專門用來收集各種watcher實例(通過Object.defineProperty重寫了屬性的存取器函數辦到的)。當組件開始掛載時(vm.$mount(vm.options.el)),組件的render函數被調用,從而觸發了屬性的get函數,該屬性對應的dep就會收集當前活躍的watcher實例(也即render watcher),掛載完畢后頁面的初次渲染就完成了。當data中的數據發生變化時會觸發對應屬性的set函數,set函數會調用該屬性對應的dep中的wathcer實例的run方法,該方法最終經過Diff算法算出頁面最小變動部分,從而實現頁面更新。 - 模板編譯系統
通過正則手段,將vue語法格式的html字符串解析成AST,最終通過字符串拼接的方式產生render和renderStatic函數 - 批量更新 & Diff 算法
頁面初次渲染后,如果data中的數據發生變化,比如a,b兩個屬性發生變化,并不是a屬性變化時更新一下頁面,b屬性變化時再更新一下頁面,而是a,b兩個屬性都變化以后只更新一次頁面(前提是ab的變化不是異步的),這就是批量更新的意思。實現的原理是內部實現了nextTick函數,觸發屬性的set函數時,會將該屬性收集的watcher放入隊列中,等此次事件循環結束后統一在下次循環時依次執行(本質上執行watcher.run方法);
Diff算法是按層級比較的,因此時間復雜度為o(n),效率上是很高效的(暫未深入研究)