Vue響應式原理概述

1 MVVM模式

Model-View-ViewModel源自MVC模式,核心是ViewModel,ViewModel做爲一個「中轉站」,對接Model層得到並轉換數據使得數據易管理、便於View層使用,又對接View層進行雙向的數據綁定。MVVM框架利用ViewModel這一層幫助開發者們作好了以前jQuery時代低效的查找、操做DOM的工做。View最終展示的不只是Model的數據,也是通過ViewModel加工後數據。html

"雖然沒有徹底遵循 MVVM 模型,可是 Vue 的設計也受到了它的啓發。所以在文檔中常常會使用 vm (ViewModel 的縮寫) 這個變量名錶示組件實例"

2 Vue雙向數據綁定

從設計思想來講,Vue採用的MVVM模式是雙向綁定的。Vue實例即充當MVVM中ViewModel層,Model驅動View更新,View層模板進行編譯後Vue實例內部數據也會更新。從開發者使用的角度來講,Vue並無提供相似AngularJS雙向數據綁定的API。雖然它經過提供v-model這個語法糖提供了部分雙向數據綁定的能力。Vue其實是單向的數據驅動視圖。vue

<input v-model="inputData" />

等價於git

<input :value="inputData"  @input="inputData = $event.target.value"/>

3 數據驅動視圖

視圖是由數據驅動生成的,對視圖的修改,不是直接操做DOM而是經過修改數據。經過利用虛擬DOM,Vue實現了數據驅動視圖。總體看一下從建立Vue實例到最後渲染到頁面發生的過程。如圖:
github

數據驅動生成視圖的過程:

1) 初始化Vue:Vue是一個類,new Vue({...})操做調用構造函數完成合並配置、初始化生命週期、事件中心,初始化Injections、state(props|data|methods|computed|watch)、provide等;
2) 掛載Vue實例到el:校驗頁面上的掛載點el,並拿到對應的template;
3) 模板編譯:由template編譯出render()函數,通過一系列的compileToFunctions-createCompiler-createCompilerCreator後,最後Parse出ast,通過優化ast,最終生成render代碼;
4) 調用render():將自定義配置中的數據和頁面模板生成的數據結合後,生成VDOM;
5) update和patch上一步的VDOM出DOM:patch提供了鉤子函數,在回調中作相應的處理生成DOM。

4 響應式原理

響應式原理指的是Vue中數據變化驅動視圖更新。實現的關鍵兩個點:數組

1)將數據變成 響應式數據
2)實現一個 觀察者模式:進行依賴收集和派發更新。

響應式數據是指經過代理對象的方式給數據添加上getter、setter屬性特性,從而使對數據的訪問、更新操做是可觀測的。Vue2使用Object.defineProperty()方法,Vue3使用的是Proxy對象。再經過觀察者模式,在訪問數據時進行依賴的收集,在數據更新時派發通知給以前收集到的依賴作更新處理。具體來講,在Vue內部,經過Observer類將數據遞歸地轉化成可觀測對象,最終生成的響應式數據對象,是一個包含了__ob__屬性的對象。在其內部定義、並調用了一系列處理函數:如walk()\defineReactive()。框架


依賴收集:發生在訪問響應式數據觸發getter函數時,收集的依賴指的是渲染Watcher,收集動做的主體即爲響應式數據自己。具體來講Vue內部實現了一個管理Watcher的Dep類(內部維護了一個數組),每一個響應式數據對象屬性值的 getter都持有一個 dep的引用。當完成一次render調用後,會觸發全部響應式數據的 getter,從而完成響應式數據Watcher的收集的過程。異步


派發更新:發生在更新響應式數據觸發setter函數時,實際上就是把以前收集好的Watcher依賴從隊列中取出來執行其update()方法的過程。其中Vue也作了一些優化,並不會每次數據改變都觸發 watcher 的回調執行,而是把這些watcher先添加到一個隊列裏,而後在nextTick後執行 flushSchedulerQueue,利用JavaScript提供的事件隊列的這種異步的方式執行更新動做。ide

5 Vue2和Vue3響應式原理的區別

Vue2使用Object.defineProperty(),Vue3使用的是Proxy。相比Object.defineProperty(),Proxy()不只能夠解決沒法觀測對象新增刪除屬性、沒法觀測數組經過索引設值、長度變化的問題,其API更爲豐富。對比Object.defineProperty()觀測對象的屬性,Proxy代理的是對象,性能也更好。
Object.defineProperty()之因此不支持數組,是由於Vue基於性能考慮沒有用,而不是由於它不支持。函數

參考:
Vue技術揭祕性能

https://ustbhuangyi.github.io...
https://www.cnblogs.com/iovec...

相關文章
相關標籤/搜索