Vue 2 3 4原始碼分析之雙向繫結原理

2021-08-15 19:20:18 字數 2374 閱讀 7815

要想實現雙向繫結需要做到兩點:1.如何監聽data物件是否改變;2.物件變化後如何去更新檢視

一、如何監聽data物件是否改變

在vue監聽data物件是否改變主要通過definereactive方法來做到的,就是利用object.defineproperty的get和set方法。如下**所示:

export function definereactive (

obj: object,

key: string,

val: any,

customsetter?: function

) // cater for pre-defined getter/setters

const getter = property && property.get

const setter = property && property.set

let childob = observe(val)

object.defineproperty(obj, key,

if (array.isarray(value))

}return value

},set: function reactivesetter (newval)

/* eslint-enable no-self-compare */

if (process.env.node_env !== 'production' && customsetter)

if (setter) else

childob = observe(newval)

dep.notify()//通知所有訂閱了該dep的觀察者watcher物件去更新檢視,watcher會呼叫updatecomponent方法去更新檢視}})

}

但是object.defineproperty也不是沒有缺點,就是它無法監聽陣列的push,shift等方法。那麼如何監聽陣列的這一些方法呢?

我們知道陣列物件本身沒有push這一些方法,都是繼承至array.prototype物件的,所以我們想到可以重寫這一些方法,但不能直接修改array.prototype物件上的方法,否則將影響所有陣列的使用。那vue是如何做到的呢?分為兩種情況:

1.如果瀏覽器支援__proto__熟悉的話,vue採用的是**模式實現的,實現方式如下:

首先vue建立了乙個繼承至array.prototype的arraymethods**物件,在該**物件中重寫了相關的陣列原生方法,

const arrayproto = array.prototype

export const arraymethods = object.create(arrayproto)

/** * intercept mutating methods and emit events

*/;[

'push',

'pop',

'shift',

'unshift',

'splice',

'sort',

'reverse'

].foreach(function (method)

const ob = this.__ob__

let inserted

switch (method)

if (inserted) ob.observearray(inserted)

// notify change

ob.dep.notify()

return result

})})

然後再將陣列物件繼承至arraymethods物件

function protoaugment (target, src: object)

2.如果瀏覽器不支援__proto__屬性,就只需在陣列物件上新增了push等方法,這樣當陣列呼叫push等方法時將不再使用array.prototype的方法,而是這一些新增的方法。

function copyaugment (target: object, src: object, keys: array) 

}

二、物件變化後如何去進行檢視渲染

首先物件變化,會觸發對於的definereactive中的set方法,在set方法中會觸發dep.notify(),該方法會觸發所有訂閱了該dep的watcher去只執行檢視渲染,可以參考

總結如下,其實vue的雙向繫結主要基於觀察者模式實現的。dep相當於被觀察物件,watcher相關於觀察者物件,在頁面首次渲染後,definereactive中的get方法就讓watcher進行了對dep的訂閱,一旦data資料變化,就呼叫dep.notify()去通知所有的訂閱了該dep的watcher,去執行渲染操作。

vue 原始碼之雙向繫結

vue 雙向繫結,問就是 object.defineproperty 劫持資料獲得狀態變更,發布訂閱者模式進行變更通知。好吧,現在地球人都知道這兩句話了,要是別人再問你實現細節,我們應該如何回答呢。也是為了讓自己更加了解,從自己大概知道和能與人清楚表達,這就是今天寫文章的目的了。閱讀前,你需要具備 ...

Vue原始碼分析之Observer

四月份真是慵懶無比的乙個月份,看著手頭上沒啥事幹,只好翻翻 啥的,看了一會vue的原始碼,忽而有點感悟,於是便記錄一下。觀察者模式一般包含發布者 publisher 和訂閱者 subscriber 兩種角色 顧名思義發布者負責發布訊息,訂閱者通過訂閱訊息響應動作了。回到vue中,在vue原始碼cor...

Vue原始碼分析

在開始原始碼分析工作之前,我們在當前篇章做好相應的準備工作,以便更好地展開分析。將原始碼fork到自己的github倉庫中 git clone 自己的github vue 位址 dist 打包之後的結果 examples 示例 src compiler 編譯相關 core vue 核心庫 compo...