雙向是指ViewModel中的data部分和View之間的雙向關(guān)系。
正向:數(shù)據(jù)驅(qū)動(dòng)頁(yè)面
反向:頁(yè)面更新數(shù)據(jù)
綁定是指自動(dòng)化處理,data改變了view隨之改變,反之也是。
不用像傳統(tǒng)方式那樣,通過(guò)onChange事件獲取用戶(hù)輸入,然后再通過(guò)改變innerHtml修改顯示。
雙向綁定都是依賴(lài)ES5中一個(gè)重要的API,Object.defineProperty
數(shù)據(jù)劫持結(jié)合發(fā)布-訂閱者的方式;通過(guò)Object.defineProperty來(lái)劫持各個(gè)屬性的getter\setter來(lái)監(jiān)聽(tīng)屬性變化,實(shí)現(xiàn)Observer監(jiān)聽(tīng)
- 監(jiān)聽(tīng)者 (Observer): 有一個(gè)監(jiān)聽(tīng)者(Observer),監(jiān)聽(tīng) data發(fā)生的變化, (通過(guò)Object.defineProperty 的get 屬性重新遍歷,修改 get 和 set 操作,還會(huì)有一個(gè)遞歸的操作,如果操作的是一個(gè)子對(duì)象,會(huì)對(duì)這個(gè)子對(duì)象重新進(jìn)行遞歸遍歷一遍保證所有的key值都是有 observer 對(duì)象的。)
- 觀(guān)察者列表 (Dep): 數(shù)據(jù)的變化會(huì)觸發(fā) Object.defineProperty 對(duì)象的set 屬性,set 會(huì)執(zhí)行對(duì)觀(guān)察者列表的觸發(fā),通知觀(guān)察者列表(Dep)
- 列表會(huì)有一個(gè)更新函數(shù),通知了它們,它們會(huì)自動(dòng)調(diào)用 updated 更新函數(shù),也就是 Dep 調(diào)用了 回調(diào),這個(gè) 回調(diào)是 觀(guān)察者 (watcher)給的
- 觀(guān)察者(watcher): watcher 拿到更新后的數(shù)據(jù)就可以更新到 view了
- 觀(guān)察者列表的updated 是怎么傳進(jìn)去的,是通過(guò) watcher 的訂閱,watcher 往觀(guān)察者列表添加新的內(nèi)容(監(jiān)聽(tīng)完后會(huì)有一步實(shí)例化 watcher 對(duì)象,想對(duì)A 操作,observer 完后會(huì)手動(dòng)調(diào)用一下watcher,實(shí)例化watcher,watcher 會(huì)調(diào)用 get,檢測(cè)watcher全局變量是否有值,有值的話(huà)會(huì)調(diào)用 deep.target,把內(nèi)容往 Dep添加)
Object.defineProperty 與 Reflect.defineProperty 的區(qū)別:
Object.defineProperty是 ES5 的用法,返回的是一個(gè)對(duì)象
Reflect.defineProperty是ES6 的用法,返回的是一個(gè)布爾值
Object.defineProperty缺點(diǎn):
深度監(jiān)聽(tīng),需要遞歸到底,一次性計(jì)算量大
無(wú)法監(jiān)聽(tīng)新增/刪除屬性(所以需要 vue.set vue.delete 實(shí)現(xiàn)新增/刪除屬性)
無(wú)法監(jiān)聽(tīng)原生數(shù)組,需要特殊處理