實(shí)現(xiàn)mvvm主要包含兩個(gè)方面西篓,數(shù)據(jù)變化更新視圖利虫,視圖變化更新數(shù)據(jù):
關(guān)鍵點(diǎn)在于data如何更新view,因?yàn)関iew更新data其實(shí)可以通過(guò)事件監(jiān)聽(tīng)即可尸诽,比如input標(biāo)簽監(jiān)聽(tīng) 'input' 事件就可以實(shí)現(xiàn)了忽孽。所以我們著重來(lái)分析下绑改,當(dāng)數(shù)據(jù)改變,如何更新視圖的兄一。
數(shù)據(jù)更新視圖的重點(diǎn)是如何知道數(shù)據(jù)變了厘线,只要知道數(shù)據(jù)變了,那么接下去的事都好處理出革。如何知道數(shù)據(jù)變了造壮,其實(shí)上文我們已經(jīng)給出答案了,就是通過(guò)Object.defineProperty( )對(duì)屬性設(shè)置一個(gè)set函數(shù),當(dāng)數(shù)據(jù)改變了就會(huì)來(lái)觸發(fā)這個(gè)函數(shù)耳璧,所以我們只要將一些需要更新的方法放在這里面就可以實(shí)現(xiàn)data更新view了成箫。
思路有了,接下去就是實(shí)現(xiàn)過(guò)程了旨枯。
實(shí)現(xiàn)過(guò)程
我們已經(jīng)知道實(shí)現(xiàn)數(shù)據(jù)的雙向綁定蹬昌,首先要對(duì)數(shù)據(jù)進(jìn)行劫持監(jiān)聽(tīng),所以我們需要設(shè)置一個(gè)監(jiān)聽(tīng)器Observer攀隔,用來(lái)監(jiān)聽(tīng)所有屬性皂贩。如果屬性發(fā)上變化了,就需要告訴訂閱者Watcher看是否需要更新昆汹。因?yàn)橛嗛喺呤怯泻芏鄠€(gè)明刷,所以我們需要有一個(gè)消息訂閱器Dep來(lái)專(zhuān)門(mén)收集這些訂閱者,然后在監(jiān)聽(tīng)器Observer和訂閱者Watcher之間進(jìn)行統(tǒng)一管理的满粗。接著辈末,我們還需要有一個(gè)指令解析器Compile,對(duì)每個(gè)節(jié)點(diǎn)元素進(jìn)行掃描和解析映皆,將相關(guān)指令對(duì)應(yīng)初始化成一個(gè)訂閱者Watcher本冲,并替換模板數(shù)據(jù)或者綁定相應(yīng)的函數(shù),此時(shí)當(dāng)訂閱者Watcher接收到相應(yīng)屬性的變化劫扒,就會(huì)執(zhí)行對(duì)應(yīng)的更新函數(shù),從而更新視圖狸膏。因此接下去我們執(zhí)行以下3個(gè)步驟沟饥,實(shí)現(xiàn)數(shù)據(jù)的雙向綁定:
1.實(shí)現(xiàn)一個(gè)監(jiān)聽(tīng)器Observer,用來(lái)劫持并監(jiān)聽(tīng)所有屬性湾戳,如果有變動(dòng)的贤旷,就通知訂閱者。
2.實(shí)現(xiàn)一個(gè)訂閱者Watcher砾脑,可以收到屬性的變化通知并執(zhí)行相應(yīng)的函數(shù)幼驶,從而更新視圖。
3.實(shí)現(xiàn)一個(gè)解析器Compile韧衣,可以?huà)呙韬徒馕雒總€(gè)節(jié)點(diǎn)的相關(guān)指令盅藻,并根據(jù)初始化模板數(shù)據(jù)以及初始化相應(yīng)的訂閱器。
流程圖如下: