vue 原始碼之雙向繫結

2021-09-28 07:04:12 字數 2380 閱讀 5930

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進行變動...