???????最近在玩React瓜富,寫了幾個demo驚醒自己其實對vue的了解還是半斤八兩鳍咱,主要還是在公司總是寫業(yè)務(wù)代碼不咋注重底層(哎,不想加班QAQ)与柑,趁此機會重新過一遍vue文檔想要稍微了解一下vue雙向綁定的原理和簡單實現(xiàn)方案谤辜。
???????首先我們先說說傳統(tǒng)的MVC模式,MVC指的是Model-View-Controller价捧。MVC模式是單向數(shù)據(jù)綁定丑念,就是將Model中的數(shù)據(jù)綁定到View(顯示層)上,在執(zhí)行Controller去修改Model中的數(shù)據(jù)后结蟋,Model會再次通知View去改變渠欺。這是一個單向循環(huán)的數(shù)據(jù)綁定操作。然而Vue不是采用MVC模式椎眯,他使用的是MVVM模式,MVVM指Model-View-ViewModel模式胳岂。MVVM是將Model中的數(shù)據(jù)綁定到ViewModel中编整,Model層的變化會通知ViewModel使其更新View層,反過來View層的變化也會通知ViewModel使其更新Model層乳丰。因此雙向綁定我便可以理解為model的數(shù)據(jù)更新能使得View層的更新掌测,并且用戶更新View層也會導(dǎo)致Model層的數(shù)據(jù)自動更新。
???????我們在網(wǎng)上隨便搜vue 雙向綁定
产园,大部分搜出的結(jié)果都會說這么一句話:vue數(shù)據(jù)雙向綁定是通過數(shù)據(jù)劫持結(jié)合發(fā)布-訂閱模式的方式來實現(xiàn)的汞斧。當初我看這句話的時候真的是完全無法理解其中含義,過了一段時間以后我再回頭看其他資料結(jié)合官方文檔的解釋才能理解(我太笨了 QAQ)什燕。接下來我就簡單的描述一下Vue的雙向綁定原理粘勒。
???????按照Vue官方文檔中的描述,我們將JS對象傳入Vue實例作為data選項屎即,Vue會遍歷這個對象的所有屬性并使用Object.defineProperty()
庙睡,將對象中的各個屬性轉(zhuǎn)化為getter和setter事富。vue定義了getter和setter并在其中設(shè)置了更新dom的方法,當對象中的這個屬性被調(diào)用或修改時(即get/set時)乘陪,vue會在屬性變化的同時執(zhí)行更新DOM的方法统台,這樣就可以及時更新在頁面上。(原理如下啡邑,Object.defineProperty()
這個API大家可以去MDN了解一下)
Object.defineProperty(data, '我要修改這個屬性的getter和setter', {
get: function(){
console.log('get返回值之前我先做點事情')
/*
* 這里是通知變化代碼
*/
return value
},
set: function(newValue){
value = newValue
console.log('set設(shè)置好以后我再做點事情')
/*
* 這里是通知更新代碼
*/
}
})
下面根據(jù)官方文檔簡單描述一下vue的雙向綁定是如何實現(xiàn)的:
???????vue中每個組件實例都對應(yīng)一個 watcher 實例贱勃,現(xiàn)在我們把目光聚焦在上圖的紫色圓中。紫色圓代表Data谤逼,組件初始化就會修改Data中每個屬性的getter和setter函數(shù)贵扰。當組件中某個屬性被get時,getter會同時通知Watcher實例森缠,讓W(xué)atcher拿個小本子記一下我這里有這么個屬性拔鹰;setter也類似,當屬性被修改執(zhí)行set時贵涵,setter也會通知watcher列肢。watcher收到通知后會檢查被改動的屬性是否記錄在小本子上并檢查是否有變動,在且有變化的情況下就繼續(xù)往下通知組件渲染函數(shù)讓它去更新虛擬DOM樹宾茂。(暫時想不到更形象的比喻了 - -)
后面我又去找了找原生JS如何實現(xiàn)vue的雙向綁定瓷马,找到一個文章寫的很棒,現(xiàn)在先在這里記錄一下這個文章:雙向綁定實現(xiàn)過程跨晴。由于我的理解還沒那么深入欧聘,暫時不寫實現(xiàn)過程了,根據(jù)前面那個文章的描述我也試著寫了一下端盆,下面是我寫的代碼地址怀骤。