想必教程大家已經看過,也動手做過一些Demo。倘若讓大家用一句話概括'“vue是什么”,你的答案會是什么?。這里Vue官方教程也給出了自己的一句話解釋。就是教程開頭的第一句話
Vue.js(讀音 /vju?/,類似于 view) 是一套構建用戶界面的漸進式框架。
這句話你可能并不陌生,但你未必真正讀懂了它。 我們注意到這句話中有一個被作者高亮的詞語—漸進式框架,其實明白了這個詞語的意思,也便讀懂了這句話,從而也就理解了Vue的核心理念。
那么漸進式框架究竟是什么意思,在解釋這個詞語之前,我們有必要先搞明白一個問題 “什么是框架?"[1]
在最初前端開發中,為了完成某個任務,我們首先利用JS從HTML文件中獲取DOM元素,隨后添加事件,最后進行一系列的JS編程操作。我們姑且把這種開發方式稱為“DOM流”吧,“DOM流”的開發方式看起來似乎很簡單實用,但是隨著業務需求不斷變動,你的麻煩就來了,整個代碼會變得越來越混亂,無法維護。舉個例子,假設現在有一個這樣的需求,有一張圖片,在被點擊時,可以記錄下被點擊的次數。 這看起來很簡單吧, 按照上面提到到開發方式,應該很快就可以搞定。 那么接下來,需求稍微發生了點變動, 要求有兩張圖片,分別被點擊時,可以記錄下各自的點擊次數。這次似乎也很簡單,只需把原先的代碼復制粘貼一份就可以了。 那么當這個需求變成五張圖片時,你會怎么做? 還是簡單復制粘貼吧,這樣完全可以完成這個需求,但是你會覺得很別扭,因為你的代碼此時變得很臃腫,存在很多重復的過程,但是似乎還在你的忍受范圍內。這時候需求又發生了微小的變動,還是五張照片分別記錄被點擊次數,不過這樣單獨羅列五張圖片似乎太占空間,現在只需要存在一個圖片的位置,通過選擇按鈕來切換被點擊的圖片。 這時候你可能會奔潰掉,因為要完成這個看似微小的改動,你原先寫的大部分代碼可能都需要被刪掉,甚至是完全清空掉,從零開始寫起,更讓人郁悶的是,即使耐著性子重新寫好了這個需求,一旦又來了新的需求,可能又要重新開始了。這還僅僅是一個單純的記錄點擊次數的任務,“DOM流”的開發方式似乎已經出現很大的問題,而在現實的開發中,復雜的業務邏輯和巨大的代碼量,更是“DOM流"根本無法承受的。
為了應對以上問題,開發人員重新梳理了代碼的組織結構,把JS代碼劃分為三個板塊,數據(M)、視圖(V)、 邏輯控制(*)。 數據板塊只含有數據內容,視圖板塊只負責更改樣式,邏輯控制負責聯系視圖板塊和數據板塊和相應的邏輯,如下圖所示。 這樣代碼結構組織的好處是顯而易見的,當需求發生變動時,只需要改動相應的板塊即可。還是拿上文中提到的記錄圖片點擊次數的需求為例,這是重新組織后的代碼 demo,可以看到這次代碼變得清晰易懂,而且你自己也可以去設想再增加某些需求,來看看需要改動代碼的程度。
其實這種開發方式,就是我們常說的MV模式,而MVC、MVVM、 MVP[2]等都是MV的衍生物, 其實叫什么模式名稱并不重要,當你現在搞清楚了這種代碼組織結構的目的,就會明白這些模式本質上都是一回事,讓數據與視圖間不會發生直接聯系。 其實說到這里,你應該知道“DOM流存在缺陷的原因,在“DOM流"中其實是把dom當做Model,我們直接從dom中獲取數據,隨后又改變dom來更新視圖,視圖和模型其實是混在一起了,代碼組織自然很混亂,不易維護。
而這種MV*的代碼組織方式,漸漸的就演變成了所謂的框架。 團隊開發中會選擇使用框架的一個重要的原因,因為框架提前設定好的代碼的組織結構讓實際開發項目的代碼有一個相對明確地方,這樣不用擔心因為團隊中某個人疏忽或特有編碼習慣, 造成代碼整體的混亂。這里說句題外話,依照現在對框架的認識,嚴格來說Bootstrap并不是一個框架,其實只是一個CSS工具集,主要用來做界面美化。而Jquery也并不涉及代碼的結構組織,只是把一些重復的操作進行簡化 (如 DOM操作 Ajax操作等),再加上對于兼容性的解決,所以只是用來方便操作的JS庫。
現在利用MV的代碼組織方式,我們擁有了可以應對需求變化的健壯代碼。在使用過程中,開發人員逐漸發現在應對有頻繁數據更新的需求時,我們總在做著同樣的工作—獲取DOM,依照新的數據來更新視圖。這些工作繁瑣且重復,實質上耗費了開發人員的精力。 為了解決這個問題,基于MV的模式的MVVM框架誕生—Knockout。它利用實例的形式,把model層內容傳入到實例所謂的view model中,利用binding方法完成view model與view之間的雙向綁定,view mode中數據變化時,view發生變化,反之亦然。這段對于Knockout描述可能有點抽象, 畢竟上沒有上代碼,但你至少知道Knockout框架能替我們完成了從數據更新后視圖相應的更新就行了,如下圖所示。
你可能會感嘆,具有這么先進理念和功能的框架,自己怎么沒用過,甚至之前沒有聽說過。這是因為Knockout誕生的時候超越了它的時代,還記得這段開頭提到MVVM框架產生的原因嗎—應對有頻繁數據更新的需求,而在當時前端頁面的大部分就只涉及靜態展示和簡單交互,不存在頻繁的數據變更,使用Jquery 足矣。就這樣,Knockout在當時并沒有流行起來,不過這個框架現在依然存在,感興趣的可以去看看,上手也很簡單 。 直到最近幾年,隨著隨著關于數據頻繁變動的需求越來越多,人們又開始重視這種自動跟新視圖的理念了。 Vue就是繼承這種理念的眾多框架之一。如下圖所示,在具有響應式系統的Vue實例中,DOM狀態只是數據狀態的一個映射 即 UI=VM(State) ,當等式右邊State改變了,頁面展示部分UI就會發生相應改變。很多人初次上手Vue時,覺得很好用,原因就是這個。不過需要注意的是,Vue的核心定位并不是一個框架[3],設計上也沒有完全遵循MVVM模式,可以看到在圖中只有State和View兩部分, Vue的核心功能強調的是狀態到界面的映射,對于代碼的結構組織并不重視, 所以單純只使用其核心功能時,它并不是一個框架,而更像一個視圖模板引擎,這也是為什么Vue開發者把其命名成讀音類似于view的原因。
現在我們來看看“漸進式”的意思。上文提到,Vue的核心的功能,是一個視圖模板引擎,但這不是說Vue就不能成為一個框架。如下圖所示,這里包含了Vue的所有部件,在聲明式渲染(視圖模板引擎)的基礎上,我們可以通過添加組件系統、客戶端路由、大規模狀態管理來構建一個完整的框架。更重要的是,這些功能相互獨立,你可以在核心功能的基礎上任意選用其他的部件,不一定要全部整合在一起。可以看到,所說的“漸進式”,其實就是Vue的使用方式,同時也體現了Vue的設計的理念
而對于“漸進式”的解釋,我在知乎上看到了一個不錯的回答,這個答案也被Vue的設計者點了贊。這個回答的角度很好,主要從與React、Angular的比較來闡述的,由于本人沒怎么用過另外這兩個框架,也就不妄加評述,所以僅把回答進行摘錄,以供參考[4]。
在我看來,漸進式代表的含義是:主張最少。
每個框架都不可避免會有自己的一些特點,從而會對使用者有一定的要求,這些要求就是主張,主張有強有弱,它的強勢程度會影響在業務開發中的使用方式。
比如說,Angular,它兩個版本都是強主張的,如果你用它,必須接受以下東西:
- 必須使用它的模塊機制- 必須使用它的依賴注入- 必須使用它的特殊形式定義組件(這一點每個視圖框架都有,難以避免)
所以Angular是帶有比較強的排它性的,如果你的應用不是從頭開始,而是要不斷考慮是否跟其他東西集成,這些主張會帶來一些困擾。
比如React,它也有一定程度的主張,它的主張主要是函數式編程的理念,比如說,你需要知道什么是副作用,什么是純函數,如何隔離副作用。它的侵入性看似沒有Angular那么強,主要因為它是軟性侵入。
Vue可能有些方面是不如React,不如Angular,但它是漸進的,沒有強主張,你可以在原有大系統的上面,把一兩個組件改用它實現,當jQuery用;也可以整個用它全家桶開發,當Angular用;還可以用它的視圖,搭配你自己設計的整個下層用。你可以在底層數據邏輯的地方用OO和設計模式的那套理念,也可以函數式,都可以,它只是個輕量視圖而已,只做了自己該做的事,沒有做不該做的事,僅此而已。
漸進式的含義,我的理解是:沒有多做職責之外的事。
好了,到這里已經解釋完了“漸進式框架”的意思,現在讓我們再回過頭來看看開頭那句話。
Vue.js(讀音 /vju?/,類似于 view) 是一套構建用戶界面的漸進式框架。
是不是對Vue有了不一樣的感覺,現在也應該知道如何去學習和使用Vue了吧。在學習中,我們沒必要一上來就搞懂Vue的每一個部件和功能,先從核心功能開始學習,逐漸擴展。 同時,在使用中,我們也沒有必要把全部件能都拿出來,需要什么用什么就是了,而且也可以把Vue很方便的與其它已有項目或框架相結合。
[1] JavaScript 設計模式設計模式-udacity
[2] MVC,MVP 和 MVVM的圖示 - 阮一峰
[3] Vue 2.0,漸進式前端解決方案-尤雨溪
[4] Vue2.0 中,“漸進式框架”和“自底向上增量開發的設計”這兩個概念是什么?-徐飛