參考
vue資料雙向繫結是通過資料劫持結合發布者-訂閱者模式的方式來實現的。
雙向繫結就是檢視上的變化能夠反映到資料上,資料上的變化也能反映到檢視上。如下圖所示:
關鍵點在於data如何更新view,因為view更新data其實可以通過事件監聽即可,比如input標籤監聽 『input』 事件就可以實現了。所以我們著重來分析下,當資料改變,如何更新檢視的。
資料更新檢視的重點是如何知道資料變了,只要知道資料變了,那麼接下去的事都好處理。我們可以通過object.defineproperty()
來實現對資料改變的監聽。object.defineproperty()
接受三個引數,第乙個是目標物件,即你要把這個屬性新增到哪個物件上,第二個是屬性名,第三個是乙個描述符物件。
如果該屬性為資料屬性,描述符物件就會包含四個屬性:configurable(能否通過delete操作符刪除),enumerable(能否通過for-in遍歷屬性),writable(能否修改屬性)和value(屬性值),前三個預設為false。如果該屬性為訪問器屬性,描述符物件就會包含四個屬性:configurable(能否通過delete操作符刪除),enumerable(能否通過for-in遍歷屬性),get(在讀取屬性時呼叫的函式)和set(在寫入屬性時呼叫的函式),get和set預設為undefined。所以我們可以把資料設定為訪問器屬性,這樣資料改變時就會觸發get和set方法,我們可以通過這兩個函式來實現對檢視的更新。
實現過程:
我們已經知道實現資料的雙向繫結,首先要對資料進行劫持監聽,所以我們需要設定乙個***observer,用來監聽所有屬性。如果屬性發上變化了,就需要告訴訂閱者watcher看是否需要更新。因為訂閱者是有很多個,所以我們需要有乙個訊息訂閱器dep來專門收集這些訂閱者,然後在***observer和訂閱者watcher之間進行統一管理的。接著,我們還需要有乙個指令解析器compile,對每個節點元素進行掃瞄和解析,將相關指令對應初始化成乙個訂閱者watcher,並替換模板資料或者繫結相應的函式,此時當訂閱者watcher接收到相應屬性的變化,就會執行對應的更新函式,從而更新檢視。因此接下去我們執行以下3個步驟,實現資料的雙向繫結:
1.實現乙個***observer,用來劫持並監聽所有屬性,如果有變動的,就通知訂閱者。
2.實現乙個訂閱者watcher,可以收到屬性的變化通知並執行相應的函式,從而更新檢視。
3.實現乙個解析器compile,可以掃瞄和解析每個節點的相關指令,並根據初始化模板資料以及初始化相應的訂閱器。
流程圖如下:
遍歷data中的所有屬性,同時通過遞迴的方式遍歷這些屬性的子屬性,通過object.defineproperty()
將這些屬性都定義為訪問器屬性,訪問器屬性自帶get和set方法,我麼通過get和set方法來監聽資料變化。
dep我們需要訊息訂閱器來收集所有的訂閱者,就好像是乙個列表,當屬性的get方法被觸發時,需要判斷是否要新增訂閱者,如果需要就在列表中增加乙個訂閱者,當set方法被觸發時就通知列表中所有的訂閱者來做出響應。
watcher
因為我們是在get函式中判斷是否要新增訂閱者的,要想把乙個訂閱者新增到列表中我們就需要在初始化這個訂閱者時觸發get函式,我們可以在dep.target上快取下訂閱者,新增成功後再將其去掉就可以了。\
compile
compile負責初始化時的編譯解析,遍歷每乙個結點,看哪些結點需要訂閱者,也負責後續為訂閱者繫結更新函式。
ok,這就是我讀了部落格後自己的總結與理解。
vue雙向資料繫結原理
vue應用的是mvvm框架,view和model分離,然後通過vm雙向資料繫結,div 原生物件即資料 var data 建立乙個 viewmodel 例項 var vm new vue 然而乙個動態資料的繫結,是怎麼實現的呢,首先vue利用es5的defineproperty方法裡的get,set...
vue雙向資料繫結原理
text id text show p var text document.getelementbyid text show document.getelementbyid show var model object.defineproperty model,name set function ne...
vue資料雙向繫結原理
vue的資料雙向繫結的小例子 html index.js function selfvue data,el,exp 對data的每一層級的屬性進行監聽,如果變化執行notify observe data 初始化模板資料的值 el.innerhtml this data exp new watcher...