vue 雙向繫結,問就是 object.defineproperty 劫持資料獲得狀態變更,發布訂閱者模式進行變更通知。好吧,現在地球人都知道這兩句話了,要是別人再問你實現細節,我們應該如何回答呢。也是為了讓自己更加了解,從自己大概知道和能與人清楚表達,這就是今天寫文章的目的了。
閱讀前,你需要具備 vue 生命週期,object.defineproperty,以及發布訂閱者模式(相關部落格)的一些知識。
...
...callhook
(vm,
'beforecreate'
)initinjections
(vm)
//注入 data/prop 資料
initprovide
(vm)
//注入完成
callhook
(vm,
'created'
)
在進入 beforecreate 週期後,會注入 data/prop 等資料,資料劫持就是發生在此時(initinjections 函式)。
function
initinjections()
)}export
function
definereactive
( obj: object, key: string, val: any ...
...)
,set
:function()
}}
把物件的屬性鍵轉換為getter/setter,一旦劫持了資料,我們就可以為所欲為了。
但是這裡只轉換了第一層資料,我們還要巢狀遍歷物件。
在轉化物件屬性 definereactive 函式中,會先 new 乙個監聽類(observer)。監聽類通過遞迴資料,把 getter/setter 附加到每個被觀察物件(讓資料變化繫結訂閱和通知這兩個行為)。
function
observe
(value)
export
class
observer
walk
(obj: object)
}
單單只是獲取資料狀態變更不行,還得傳送通知。
了解發布訂閱者模式就該知道,訂閱者(觀察者)把自己想訂閱的事件註冊到排程中心,當該事件觸發時候,發布者(目標)發布該事件到排程中心,由排程中心統一排程訂閱者註冊到排程中心的處理**。
我們通過 getter 為每個訂閱者訂閱事件,setter 來傳送通知。
export
function
definereactive
( obj, key, val ...
...)
,set
:function()
}}
在 definereactive 的 get 裡面訂閱事件。然後在 set 中傳送通知。
export
class
dep//訂閱
depend()
}//傳送通知
notify()
}//新增依賴(訂閱者)
addsub
(sub: watcher)
}
dep.target 後續會講到,指向目標 watcher 例項
...
...callhook
(vm,
'beforemount'
)new
watcher()
......
在 beforemount 生命週期後,會 new 乙個 watcher 物件。
export
class
watcher
get(
)adddep
(dep)
update()
}
生成訂閱者 watcher,會執行一次資料的 getter(通過監聽類遞迴,監聽並讓每乙個屬性都有乙個排程中心),然後通過訂閱事件,把這個訂閱者關聯到所有排程中心的依賴內(通過 dep.target 的指向互相呼叫)。當資料變化時,該處的排程中心就會通知相應的訂閱者。
每個資料都有乙個排程中心,每個元件例項都有乙個訂閱者
實現資料的雙向繫結,首先要對資料進行劫持監聽,所以需要設定乙個***observer,用來監聽所有屬性。如果屬性發上變化了,就需要告訴訂閱者watcher看是否需要更新。我們通過訊息排程中心dep來專門收集這些訂閱者並發布訊息通知,以此在***observer和訂閱者watcher之間進行統一管理。
vue原始碼學習 vue雙向繫結原理
vue充分利用了object.defineproperty 方法,通過發布訂閱模式,在對data屬性的讀寫操作,轉換成get set方法,當資料變化時通知檢視更新。定義 object.defineproperty 是直接在物件上定義乙個新屬性或者可以直接修改乙個現有屬性,並返回該物件。let dem...
Vue 2 3 4原始碼分析之雙向繫結原理
要想實現雙向繫結需要做到兩點 1.如何監聽data物件是否改變 2.物件變化後如何去更新檢視 一 如何監聽data物件是否改變 在vue監聽data物件是否改變主要通過definereactive方法來做到的,就是利用object.defineproperty的get和set方法。如下 所示 exp...
Vue雙向繫結
把乙個普通物件 a 傳給 vue 例項作為它的 data 選項,vue.js 將遍歷它的屬性,用object.defineproperty 將它們轉為 getter setter,如圖綠色的部分所示。每次使用者更改data裡的資料的時候,比如a.b 1,setter就會重新通知watcher進行變動...