繼續(xù)理解vue的雙向綁定
首先,雙向綁定的作用是,為了達(dá)到view --> model / model --> view 從而達(dá)到mvvm,為了實(shí)現(xiàn)這個效果,應(yīng)分為以下三步進(jìn)行操作。
- v-model,{{...}},實(shí)現(xiàn)輸入框與文本節(jié)點(diǎn)與data的綁定
- view --> model ,input輸入框改變時,改變數(shù)據(jù)模型(v-text或{{}})中的數(shù)據(jù)
- model --> view , 數(shù)據(jù)模型中的數(shù)據(jù),因?yàn)楦鞣N操作而改變時,input中的值需要自動改變
1,使用文檔片段來處理節(jié)點(diǎn),將掛載的目標(biāo)子節(jié)點(diǎn)劫持之后再返回到視圖中
DocumentFragment(文檔片段)可以看作節(jié)點(diǎn)容器,它可以包含多個子節(jié)點(diǎn),當(dāng)我們將它插入到DOM中時,只有它的子節(jié)點(diǎn)會插入目標(biāo)節(jié)點(diǎn),所以把它看作一組節(jié)點(diǎn)的容器。使用DocumentFragment處理節(jié)點(diǎn),速度和性能遠(yuǎn)遠(yuǎn)優(yōu)于直接操作DOM。Vue進(jìn)行編譯時,就是將掛載目標(biāo)的所有子節(jié)點(diǎn)劫持(真的是劫持)到DocumentFragment中,經(jīng)過一番處理后,再將DocumentFragment整體返回插入掛載目標(biāo)。
2,利用訪問器屬性,實(shí)現(xiàn)view改變,改變model
利用訪問器屬性的set監(jiān)聽,當(dāng)view發(fā)生改變時,將data中的text劫持為vm的訪問器屬性(因?yàn)樵L問器屬性會被優(yōu)先訪問,與其同名的屬性會被忽略,所以謂之劫持)
Object.defineProperty(obj,"a",{
get:function(){},
set:function(newVal){
//更新node text屬性的值
}
})
當(dāng)我們在輸入框輸入數(shù)據(jù)的時候,首先觸發(fā)input事件(或者keyup、change事件),在相應(yīng)的事件處理程序中,我們獲取輸入框的value并賦值給vm實(shí)例的text屬性。我們會利用defineProperty將data中的text劫持為vm的訪問器屬性,因此給vm.text賦值,就會觸發(fā)set方法。在set方法中主要做兩件事,第一是更新屬性的值,第二留到任務(wù)三再說。
3,發(fā)布 - 訂閱者模式
需要監(jiān)聽當(dāng)model中的data發(fā)送改變時,改變view。首先,這里的訂閱者是v-text和v-model或{{}}等等,每當(dāng)vm中返回一個新的data,則為此data添加一個dep主題對象,當(dāng)有指令綁定了此data則生成一個watcher(暫時不添加到Dep),當(dāng)set(作為發(fā)布者),被觸發(fā)之后,通知訂閱者watcher,執(zhí)行相應(yīng)操作。watcher做了以下事情
- 將自己賦給了一個全局變量
Dep.target - 進(jìn)而觸發(fā)了watcher
自身的get方法,自身get方法獲取了對應(yīng)屬性的值,從而觸發(fā)了對應(yīng)屬性的get方法 -
對應(yīng)屬性的get方法檢測到全局Dep屬性非空后,將該watcher添加到該data的dep主題對象中,然后返回了屬性的值到watcher.value中 - 再然后
wather的get方法繼續(xù)執(zhí)行下一步,將this.value賦值給this.node.nodeValue,從而更新視圖。 - 最后,將全局變量
Dep.target設(shè)為null,Dep.target作為watcher和主題對象dep間溝通的唯一橋梁,使用完后要保持為空。