來自大神郝晨光
Vue中雙向數(shù)據(jù)綁定是如何實(shí)現(xiàn)的
vue.js 則是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個(gè)屬性的setter,getter,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。
詳述虛擬DOM中的diff算法
首先要先講一下虛擬DOM是如何實(shí)現(xiàn)的
虛擬DOM是通過js語法來在內(nèi)存中維護(hù)一個(gè)通過數(shù)據(jù)解構(gòu)描述出來的一個(gè)模擬DOM樹,當(dāng)數(shù)據(jù)發(fā)生改變的時(shí)候,會(huì)先對(duì)虛擬DOM進(jìn)行模擬修改,然后在通過新的虛擬DOM樹與舊的虛擬DOM樹來對(duì)比,而這個(gè)對(duì)比就是通過diff算法來進(jìn)行的
虛擬DOM最大的意義不在于性能的提升(JavaScript對(duì)象比DOM對(duì)象性能高),而在于抽象了DOM的具體實(shí)現(xiàn)(對(duì)DOM進(jìn)行了一層抽象)
接著,來看一下diff算法是如何進(jìn)行比對(duì)的
正常的diff算法,是通過層層對(duì)比,單單對(duì)比來進(jìn)行的,對(duì)于我們的前端性能來說,很明顯是不可以這樣實(shí)現(xiàn)的。

前端的虛擬DOM對(duì)比
所以,前端的diff算法是通過以下步驟來實(shí)現(xiàn)的
步驟一:用JS對(duì)象模擬DOM樹
步驟二:比較兩棵虛擬DOM樹的差異
步驟三:把差異應(yīng)用到真正的DOM樹上
同時(shí)維護(hù)新舊兩棵虛擬DOM樹,當(dāng)數(shù)據(jù)發(fā)生改變的時(shí)候,開始執(zhí)行對(duì)比
首先對(duì)根元素進(jìn)行對(duì)比,如果根元素發(fā)生改變就直接對(duì)根元素替換
如果根元素沒有發(fā)生改變的話,再對(duì)下一層元素進(jìn)行對(duì)比,如果對(duì)比發(fā)現(xiàn)元素發(fā)生刪除,就執(zhí)行刪除,發(fā)現(xiàn)元素被替換就執(zhí)行替換,發(fā)現(xiàn)添加了新的元素就執(zhí)行添加
對(duì)比的同時(shí),會(huì)通過key值來判斷元素是否發(fā)生改變,判斷元素是僅僅位置發(fā)生改變還是需要整個(gè)替換或刪除
如果不是元素發(fā)生改變的話,再對(duì)內(nèi)容進(jìn)行對(duì)比,如果是內(nèi)容發(fā)生改變的話,就直接修改內(nèi)容
其實(shí)就是進(jìn)行逐層對(duì)比,再通過不同的對(duì)比來判斷執(zhí)行不同的操作
Vue提供了幾種腳手架模板
webpack- 一個(gè)全面的webpack+vue-loader的模板,功能包括熱加載,linting,檢測和CSS擴(kuò)展。
webpack-simple- 一個(gè)簡單webpack+vue-loader的模板,不包含其他功能,讓你快速的搭建vue的開發(fā)環(huán)境。
browserify- 一個(gè)全面的Browserify+vueify 的模板,功能包括熱加載,linting,單元檢測。
browserify-simple- 一個(gè)簡單Browserify+vueify的模板,不包含其他功能,讓你快速的搭建vue的開發(fā)環(huán)境。
simple- 一個(gè)最簡單的單頁應(yīng)用模板。
pwa- 一個(gè)集成pwa環(huán)境的webapp的模板
常見的幾種MVVM的實(shí)現(xiàn)方式
實(shí)現(xiàn)數(shù)據(jù)綁定的做法有大致如下幾種:
發(fā)布者-訂閱者模式(backbone.js)
臟值檢查(angular.js)
數(shù)據(jù)劫持(vue.js)
發(fā)布者-訂閱者模式
一般通過sub,pub的方式實(shí)現(xiàn)數(shù)據(jù)和視圖的綁定監(jiān)聽,
更新數(shù)據(jù)方式通常做法是vm.set('property', value)。
這種方式現(xiàn)在畢竟太low了,我們更希望通過vm.property = value這種方式更新數(shù)據(jù),同時(shí)自動(dòng)更新視圖,于是有了下面兩種方式。
臟值檢查
angular.js 是通過臟值檢測的方式比對(duì)數(shù)據(jù)是否有變更,來決定是否更新視圖,
最簡單的方式就是通過 setInterval() 定時(shí)輪詢檢測數(shù)據(jù)變動(dòng),
angular只有在指定的事件觸發(fā)時(shí)進(jìn)入臟值檢測,大致如下:
1、DOM事件,譬如用戶輸入文本,點(diǎn)擊按鈕等。(ng-click)
2、XHR響應(yīng)事件 ($http)
3、瀏覽器Location變更事件 ($location)
4、Timer事件($timeout,$interval)
5、執(zhí)行$digest()或$apply()
數(shù)據(jù)劫持
vue.js 則是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,
通過Object.defineProperty()來劫持各個(gè)屬性的setter,getter,
在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。