名詞解釋
- 瀏覽器標準:本文中作為es6、css3、h5的統稱
我們為什麼要學習vue的實現
我們用vue,是因為它是當前業界最佳的解決方案之一,但前端技術方案迭代及工業標準化發展的浪潮,大概率不會在vue這裡到達終點。
jquery沒有死,它的基因已經注入瀏覽器標準。而webcomponent shadow dom的靈感,同樣有受到vue和react的vdom技術的啟發。當然vue也在進化,但要知道,vue的競爭對手,並不是react,而是瀏覽器的標準化程式。當webcomponent成為主流,我們現在津津樂道的vdom技術也就完成了過渡的使命。
所以我們要有危機感和好奇心,不能過渡依賴vue。我們需要搞清楚在Vue的黑盒中,都做了什麼magic。同時,我們也能學習到很多現代軟體工程的方法和設計模式,比如tdd、代理模式、觀察者模式、封裝和解耦的藝術。
Vue原始碼為什麼難讀
- 功能繁多
我們讀vue原始碼的目的,首先是想了解全貌及部分核心feature的實現,比如雙向繫結、vnode渲染等。而Vue原始碼中包含了太多非核心程式碼,比如keep alive、dynamic component、functional component等,這些並不是不重要,僅僅是我們暫時對它的實現並不太感興趣,這些程式碼的干擾會阻礙我們對核心部分的理解。
- 向後相容
Vue原始碼中包含大量向後相容程式碼,但隨著瀏覽器標準從主流框架中吸取精華,以及主流瀏覽器向瀏覽器標準的靠攏,vue作為框架所承擔的責任會越來越小,舉個最簡單的例子,用ES6的Proxy實現雙向繫結,就比Vue2.x中defineProperty的hack做法要簡潔很多。而當webcomponent火候成熟,vue甚至連vdom都不用做了。所以vue3的實現一定會比vue2簡單,這已經是官方確定的。我判斷vue4的實現一定會更精簡,而這個趨勢一直持續到vue退出歷史舞臺。
為什麼要從0寫一個vue
既然我們要學習vue的實現,而vue的原始碼又包含太多的噪音,難以梳理。縱觀全網,雖然原始碼分析的文章和教程層出不窮,但思路大多依然埋沒在vue程式碼的複雜細節中。那麼,我們為何不幹掉不感興趣的功能,不care瀏覽器相容性,只用最新的技術,撥開迷霧去寫一個最簡化的Vue呢?
此專案將按Vue3.0公開的思路,用測試驅動開發的方法,一步一步寫一個最簡化的Vue,我會盡量確保每一個commit都容易理解。建議跟隨下面步驟做,你將會對Vue有個清晰的理解。
測試驅動開發~why?
軟體工程上,按我的理解,完全自上而下的設計(瀑布模型),已經是過時的方法。即使超大型計算機專案,比如作業系統級別的工程,也是巨集觀自上而下,微觀上下結合(敏捷開發)。而TDD是一種上下結合的程式設計實踐,對於每個模組,首先設計測試用例,再寫程式碼實現出來。有以下好處:
- 控制質量,便於迴歸測試,提高開發效率
- test case即文件
- 粗略的頂層設計後(包括產品設計和技術設計),即可自下而上開始程式設計,避免過渡設計
步驟
由於tdd具有強大的test case即文件的基因,所以要理解每一步做了什麼事情,只需要看對應的test case程式碼即可。
下面每步將按diff的形式給出,必要的地方會加comment。大段整體的闡述會寫在diff頁面的底部評論區,針對某段程式碼的comment會穿插其中。歡迎留言和提issue。
階段1: Basic
這部分,我們從0做起,實現一些基礎feature,不求做到完善
執行npm run test後點選彈出瀏覽器頁面中的DEBUG按鈕即可看到效果
階段2: 完善mvvm
這部分我們完善mvvm到實現vue2.x的所有feature,並實現vue3.0公開的一個重要feature, 官方說法是"Detection of property addition / deletion",在vue2.x中,我們需要用$set。
執行npm run test後點選彈出瀏覽器頁面中的DEBUG按鈕即可看到效果
整理心情,再出發
階段3: 支援元件
階段4: Computed & watch
為了解決改變多個data會觸發多次render的問題
var cb = jasmine.createSpy('cb');
var vm = new Vue({
data () {
return {
a:1,
b:2,
}
},
render (h) {
cb()
return h('p', null, this.a + this.b)
}
}).$mount()
expect(cb).toHaveBeenCalledTimes(1)
vm.a = 10
vm.b = 11
setTimeout(_ => {
expect(cb).toHaveBeenCalledTimes(2) // change 'a' and 'b' only trigger one render
done()
})
複製程式碼
Todo list
-
Patch
-
Scoped Slot
補充
virtual dom vs shadow dom
上面對於virtual dom和shadow dom有些混淆,為了不誤導大家,這裡推薦兩篇文章
所以,未來vue的發展有兩種可能:
-
可能還會做virtual dom,但virtual dom實際渲染出來會是一個web component,現在vue的scoped css,也將被shadow dom取代。
-
但還有一種可能。virtual dom存在的意義是由於考慮到操作dom開銷大,所以要merge對dom操作。但操作shadow dom會快很多,所有我對未來virtual dom是否還有必要保持懷疑。