想必教程大家已經(jīng)看過,也動(dòng)手做過一些Demo。倘若讓大家用一句話概括'“vue是什么”浑彰,你的答案會(huì)是什么?咨演。這里Vue官方教程也給出了自己的一句話解釋闸昨。就是教程開頭的第一句話
Vue.js(讀音 /vju?/蚯斯,類似于 view) 是一套構(gòu)建用戶界面的漸進(jìn)式框架薄风。
這句話你可能并不陌生,但你未必真正讀懂了它拍嵌。 我們注意到這句話中有一個(gè)被作者高亮的詞語—漸進(jìn)式框架遭赂,其實(shí)明白了這個(gè)詞語的意思,也便讀懂了這句話横辆,從而也就理解了Vue的核心理念撇他。
那么漸進(jìn)式框架究竟是什么意思,在解釋這個(gè)詞語之前,我們有必要先搞明白一個(gè)問題 “什么是框架困肩?"[1]
在最初前端開發(fā)中划纽,為了完成某個(gè)任務(wù),我們首先利用JS從HTML文件中獲取DOM元素锌畸,隨后添加事件勇劣,最后進(jìn)行一系列的JS編程操作。我們姑且把這種開發(fā)方式稱為“DOM流”吧潭枣,“DOM流”的開發(fā)方式看起來似乎很簡單實(shí)用比默,但是隨著業(yè)務(wù)需求不斷變動(dòng),你的麻煩就來了盆犁,整個(gè)代碼會(huì)變得越來越混亂命咐,無法維護(hù)。舉個(gè)例子谐岁,假設(shè)現(xiàn)在有一個(gè)這樣的需求醋奠,有一張圖片,在被點(diǎn)擊時(shí)伊佃,可以記錄下被點(diǎn)擊的次數(shù)钝域。 這看起來很簡單吧, 按照上面提到到開發(fā)方式锭魔,應(yīng)該很快就可以搞定例证。 那么接下來,需求稍微發(fā)生了點(diǎn)變動(dòng)迷捧, 要求有兩張圖片织咧,分別被點(diǎn)擊時(shí),可以記錄下各自的點(diǎn)擊次數(shù)漠秋。這次似乎也很簡單笙蒙,只需把原先的代碼復(fù)制粘貼一份就可以了。 那么當(dāng)這個(gè)需求變成五張圖片時(shí)庆锦,你會(huì)怎么做捅位? 還是簡單復(fù)制粘貼吧,這樣完全可以完成這個(gè)需求搂抒,但是你會(huì)覺得很別扭艇搀,因?yàn)槟愕拇a此時(shí)變得很臃腫,存在很多重復(fù)的過程求晶,但是似乎還在你的忍受范圍內(nèi)焰雕。這時(shí)候需求又發(fā)生了微小的變動(dòng),還是五張照片分別記錄被點(diǎn)擊次數(shù)芳杏,不過這樣單獨(dú)羅列五張圖片似乎太占空間矩屁,現(xiàn)在只需要存在一個(gè)圖片的位置辟宗,通過選擇按鈕來切換被點(diǎn)擊的圖片。 這時(shí)候你可能會(huì)奔潰掉吝秕,因?yàn)橐瓿蛇@個(gè)看似微小的改動(dòng)泊脐,你原先寫的大部分代碼可能都需要被刪掉,甚至是完全清空掉烁峭,從零開始寫起晨抡,更讓人郁悶的是,即使耐著性子重新寫好了這個(gè)需求则剃,一旦又來了新的需求耘柱,可能又要重新開始了。這還僅僅是一個(gè)單純的記錄點(diǎn)擊次數(shù)的任務(wù)棍现,“DOM流”的開發(fā)方式似乎已經(jīng)出現(xiàn)很大的問題调煎,而在現(xiàn)實(shí)的開發(fā)中,復(fù)雜的業(yè)務(wù)邏輯和巨大的代碼量己肮,更是“DOM流"根本無法承受的士袄。
為了應(yīng)對以上問題,開發(fā)人員重新梳理了代碼的組織結(jié)構(gòu)谎僻,把JS代碼劃分為三個(gè)板塊娄柳,數(shù)據(jù)(M)、視圖(V)艘绍、 邏輯控制(*)赤拒。 數(shù)據(jù)板塊只含有數(shù)據(jù)內(nèi)容,視圖板塊只負(fù)責(zé)更改樣式诱鞠,邏輯控制負(fù)責(zé)聯(lián)系視圖板塊和數(shù)據(jù)板塊和相應(yīng)的邏輯挎挖,如下圖所示。 這樣代碼結(jié)構(gòu)組織的好處是顯而易見的航夺,當(dāng)需求發(fā)生變動(dòng)時(shí)蕉朵,只需要改動(dòng)相應(yīng)的板塊即可。還是拿上文中提到的記錄圖片點(diǎn)擊次數(shù)的需求為例阳掐,這是重新組織后的代碼 demo始衅,可以看到這次代碼變得清晰易懂,而且你自己也可以去設(shè)想再增加某些需求缭保,來看看需要改動(dòng)代碼的程度汛闸。
其實(shí)這種開發(fā)方式,就是我們常說的MV模式涮俄,而MVC蛉拙、MVVM尸闸、 MVP[2]等都是MV的衍生物彻亲, 其實(shí)叫什么模式名稱并不重要孕锄,當(dāng)你現(xiàn)在搞清楚了這種代碼組織結(jié)構(gòu)的目的,就會(huì)明白這些模式本質(zhì)上都是一回事苞尝,讓數(shù)據(jù)與視圖間不會(huì)發(fā)生直接聯(lián)系畸肆。 其實(shí)說到這里,你應(yīng)該知道“DOM流存在缺陷的原因宙址,在“DOM流"中其實(shí)是把dom當(dāng)做Model轴脐,我們直接從dom中獲取數(shù)據(jù),隨后又改變dom來更新視圖抡砂,視圖和模型其實(shí)是混在一起了大咱,代碼組織自然很混亂,不易維護(hù)注益。
而這種MV*的代碼組織方式碴巾,漸漸的就演變成了所謂的框架。 團(tuán)隊(duì)開發(fā)中會(huì)選擇使用框架的一個(gè)重要的原因丑搔,因?yàn)榭蚣芴崆霸O(shè)定好的代碼的組織結(jié)構(gòu)讓實(shí)際開發(fā)項(xiàng)目的代碼有一個(gè)相對明確地方厦瓢,這樣不用擔(dān)心因?yàn)閳F(tuán)隊(duì)中某個(gè)人疏忽或特有編碼習(xí)慣, 造成代碼整體的混亂啤月。這里說句題外話煮仇,依照現(xiàn)在對框架的認(rèn)識(shí),嚴(yán)格來說Bootstrap并不是一個(gè)框架谎仲,其實(shí)只是一個(gè)CSS工具集浙垫,主要用來做界面美化。而Jquery也并不涉及代碼的結(jié)構(gòu)組織郑诺,只是把一些重復(fù)的操作進(jìn)行簡化 (如 DOM操作 Ajax操作等)绞呈,再加上對于兼容性的解決,所以只是用來方便操作的JS庫间景。
現(xiàn)在利用MV的代碼組織方式佃声,我們擁有了可以應(yīng)對需求變化的健壯代碼。在使用過程中倘要,開發(fā)人員逐漸發(fā)現(xiàn)在應(yīng)對有頻繁數(shù)據(jù)更新的需求時(shí)圾亏,我們總在做著同樣的工作—獲取DOM,依照新的數(shù)據(jù)來更新視圖封拧。這些工作繁瑣且重復(fù)志鹃,實(shí)質(zhì)上耗費(fèi)了開發(fā)人員的精力。 為了解決這個(gè)問題泽西,基于MV的模式的MVVM框架誕生—Knockout曹铃。它利用實(shí)例的形式,把model層內(nèi)容傳入到實(shí)例所謂的view model中捧杉,利用binding方法完成view model與view之間的雙向綁定陕见,view mode中數(shù)據(jù)變化時(shí)秘血,view發(fā)生變化,反之亦然评甜。這段對于Knockout描述可能有點(diǎn)抽象灰粮, 畢竟上沒有上代碼,但你至少知道Knockout框架能替我們完成了從數(shù)據(jù)更新后視圖相應(yīng)的更新就行了忍坷,如下圖所示粘舟。
你可能會(huì)感嘆,具有這么先進(jìn)理念和功能的框架佩研,自己怎么沒用過柑肴,甚至之前沒有聽說過。這是因?yàn)镵nockout誕生的時(shí)候超越了它的時(shí)代旬薯,還記得這段開頭提到MVVM框架產(chǎn)生的原因嗎—應(yīng)對有頻繁數(shù)據(jù)更新的需求嘉抒,而在當(dāng)時(shí)前端頁面的大部分就只涉及靜態(tài)展示和簡單交互,不存在頻繁的數(shù)據(jù)變更袍暴,使用Jquery 足矣些侍。就這樣,Knockout在當(dāng)時(shí)并沒有流行起來政模,不過這個(gè)框架現(xiàn)在依然存在岗宣,感興趣的可以去看看,上手也很簡單 淋样。 直到最近幾年耗式,隨著隨著關(guān)于數(shù)據(jù)頻繁變動(dòng)的需求越來越多,人們又開始重視這種自動(dòng)跟新視圖的理念了趁猴。 Vue就是繼承這種理念的眾多框架之一刊咳。如下圖所示,在具有響應(yīng)式系統(tǒng)的Vue實(shí)例中儡司,DOM狀態(tài)只是數(shù)據(jù)狀態(tài)的一個(gè)映射 即 UI=VM(State) 娱挨,當(dāng)?shù)仁接疫匰tate改變了,頁面展示部分UI就會(huì)發(fā)生相應(yīng)改變捕犬。很多人初次上手Vue時(shí)跷坝,覺得很好用,原因就是這個(gè)碉碉。不過需要注意的是柴钻,Vue的核心定位并不是一個(gè)框架[3],設(shè)計(jì)上也沒有完全遵循MVVM模式垢粮,可以看到在圖中只有State和View兩部分贴届, Vue的核心功能強(qiáng)調(diào)的是狀態(tài)到界面的映射,對于代碼的結(jié)構(gòu)組織并不重視, 所以單純只使用其核心功能時(shí)毫蚓,它并不是一個(gè)框架占键,而更像一個(gè)視圖模板引擎,這也是為什么Vue開發(fā)者把其命名成讀音類似于view的原因绍些。
現(xiàn)在我們來看看“漸進(jìn)式”的意思捞慌。上文提到耀鸦,Vue的核心的功能柬批,是一個(gè)視圖模板引擎,但這不是說Vue就不能成為一個(gè)框架袖订。如下圖所示氮帐,這里包含了Vue的所有部件,在聲明式渲染(視圖模板引擎)的基礎(chǔ)上洛姑,我們可以通過添加組件系統(tǒng)上沐、客戶端路由、大規(guī)模狀態(tài)管理來構(gòu)建一個(gè)完整的框架楞艾。更重要的是参咙,這些功能相互獨(dú)立,你可以在核心功能的基礎(chǔ)上任意選用其他的部件硫眯,不一定要全部整合在一起蕴侧。可以看到两入,所說的“漸進(jìn)式”净宵,其實(shí)就是Vue的使用方式,同時(shí)也體現(xiàn)了Vue的設(shè)計(jì)的理念
而對于“漸進(jìn)式”的解釋裹纳,我在知乎上看到了一個(gè)不錯(cuò)的回答择葡,這個(gè)答案也被Vue的設(shè)計(jì)者點(diǎn)了贊。這個(gè)回答的角度很好剃氧,主要從與React敏储、Angular的比較來闡述的,由于本人沒怎么用過另外這兩個(gè)框架朋鞍,也就不妄加評(píng)述虹曙,所以僅把回答進(jìn)行摘錄,以供參考[4]番舆。
在我看來酝碳,漸進(jìn)式代表的含義是:主張最少。
每個(gè)框架都不可避免會(huì)有自己的一些特點(diǎn)恨狈,從而會(huì)對使用者有一定的要求疏哗,這些要求就是主張,主張有強(qiáng)有弱禾怠,它的強(qiáng)勢程度會(huì)影響在業(yè)務(wù)開發(fā)中的使用方式返奉。
比如說贝搁,Angular,它兩個(gè)版本都是強(qiáng)主張的芽偏,如果你用它雷逆,必須接受以下東西:
- 必須使用它的模塊機(jī)制- 必須使用它的依賴注入- 必須使用它的特殊形式定義組件(這一點(diǎn)每個(gè)視圖框架都有,難以避免)
所以Angular是帶有比較強(qiáng)的排它性的污尉,如果你的應(yīng)用不是從頭開始膀哲,而是要不斷考慮是否跟其他東西集成,這些主張會(huì)帶來一些困擾被碗。
比如React某宪,它也有一定程度的主張,它的主張主要是函數(shù)式編程的理念锐朴,比如說兴喂,你需要知道什么是副作用,什么是純函數(shù)焚志,如何隔離副作用衣迷。它的侵入性看似沒有Angular那么強(qiáng),主要因?yàn)樗擒浶郧秩搿?/p>
Vue可能有些方面是不如React酱酬,不如Angular壶谒,但它是漸進(jìn)的,沒有強(qiáng)主張岳悟,你可以在原有大系統(tǒng)的上面佃迄,把一兩個(gè)組件改用它實(shí)現(xiàn),當(dāng)jQuery用贵少;也可以整個(gè)用它全家桶開發(fā)呵俏,當(dāng)Angular用;還可以用它的視圖滔灶,搭配你自己設(shè)計(jì)的整個(gè)下層用普碎。你可以在底層數(shù)據(jù)邏輯的地方用OO和設(shè)計(jì)模式的那套理念,也可以函數(shù)式录平,都可以麻车,它只是個(gè)輕量視圖而已,只做了自己該做的事斗这,沒有做不該做的事动猬,僅此而已。
漸進(jìn)式的含義表箭,我的理解是:沒有多做職責(zé)之外的事赁咙。
好了,到這里已經(jīng)解釋完了“漸進(jìn)式框架”的意思,現(xiàn)在讓我們再回過頭來看看開頭那句話彼水。
Vue.js(讀音 /vju?/崔拥,類似于 view) 是一套構(gòu)建用戶界面的漸進(jìn)式框架。
是不是對Vue有了不一樣的感覺凤覆,現(xiàn)在也應(yīng)該知道如何去學(xué)習(xí)和使用Vue了吧链瓦。在學(xué)習(xí)中,我們沒必要一上來就搞懂Vue的每一個(gè)部件和功能盯桦,先從核心功能開始學(xué)習(xí)慈俯,逐漸擴(kuò)展。 同時(shí)俺附,在使用中肥卡,我們也沒有必要把全部件能都拿出來溪掀,需要什么用什么就是了事镣,而且也可以把Vue很方便的與其它已有項(xiàng)目或框架相結(jié)合。
[1] JavaScript 設(shè)計(jì)模式設(shè)計(jì)模式-udacity
[2] MVC,MVP 和 MVVM的圖示 - 阮一峰
[3] Vue 2.0揪胃,漸進(jìn)式前端解決方案-尤雨溪
[4] Vue2.0 中璃哟,“漸進(jìn)式框架”和“自底向上增量開發(fā)的設(shè)計(jì)”這兩個(gè)概念是什么?-徐飛