選擇 Vue 而不選擇 Angular,有下面幾個(gè)原因,當(dāng)然不是對(duì)每個(gè)人都適合:
在 API 與設(shè)計(jì)兩方面上 Vue.js 都比 Angular 簡(jiǎn)單得多,因此你可以快速地掌握它的全部特性并投入開(kāi)發(fā)。
Vue.js 是一個(gè)更加靈活開(kāi)放的解決方案。它允許你以希望的方式組織應(yīng)用程序,而不是任何時(shí)候都必須遵循 Angular 制定的規(guī)則。它僅僅是一個(gè)視圖層,所以你可以將它嵌入一個(gè)現(xiàn)有頁(yè)面而不一定要做成一個(gè)龐大的單頁(yè)應(yīng)用。在配合其他庫(kù)方面它給了你更大的的空間,但相應(yīng),你也需要做更多的架構(gòu)決策。例如,Vue.js 核心默認(rèn)不包含路由和 Ajax 功能,并且通常假定你在應(yīng)用中使用了一個(gè)模塊構(gòu)建系統(tǒng)。這可能是最重要的區(qū)別。
Angular 使用雙向綁定,Vue 也支持雙向綁定,不過(guò)默認(rèn)為單向綁定,數(shù)據(jù)從父組件單向傳給子組件。在大型應(yīng)用中使用單向綁定讓數(shù)據(jù)流易于理解。
在 Vue.js 中指令和組件分得更清晰。指令只封裝 DOM 操作,而組件代表一個(gè)自給自足的獨(dú)立單元 —— 有自己的視圖和數(shù)據(jù)邏輯。在 Angular 中兩者有不少相混的地方。
v-for 上使用 track-by。有意思的是,Angular 2 和 Vue 用相似的設(shè)計(jì)解決了一些 Angular 1 中存在的問(wèn)題。
React.js 和 Vue.js 確實(shí)有一些相似 —— 它們都提供數(shù)據(jù)驅(qū)動(dòng)、可組合搭建的視圖組件。當(dāng)然它們也有許多不同。
首先,內(nèi)部實(shí)現(xiàn)本質(zhì)上不同。React 的渲染建立在 Virtual DOM 上——一種在內(nèi)存中描述 DOM 樹(shù)狀態(tài)的數(shù)據(jù)結(jié)構(gòu)。當(dāng)狀態(tài)發(fā)生變化時(shí),React 重新渲染 Virtual DOM,比較計(jì)算之后給真實(shí) DOM 打補(bǔ)丁。
Virtual DOM 提供了一個(gè)函數(shù)式的方法描述視圖,這真的很棒。因?yàn)樗皇褂脭?shù)據(jù)觀察機(jī)制,每次更新都會(huì)重新渲染整個(gè)應(yīng)用,因此從定義上保證了視圖與數(shù)據(jù)的同步。它也開(kāi)辟了 JavaScript 同構(gòu)應(yīng)用的可能性。
Vue.js 不使用 Virtual DOM 而是使用真實(shí) DOM 作為模板,數(shù)據(jù)綁定到真實(shí)節(jié)點(diǎn)。Vue.js 的應(yīng)用環(huán)境必須提供 DOM。但是,相對(duì)于常見(jiàn)的誤解——Virtual DOM 讓 React 比其它的都快, Vue.js 實(shí)際上性能比 React 好,而且?guī)缀醪挥檬止?yōu)化。而 React,為了最優(yōu)化的渲染需要處處實(shí)現(xiàn) shouldComponentUpdate 或使用不可變數(shù)據(jù)結(jié)構(gòu)。
在 API 方面,React(或 JSX)的一個(gè)問(wèn)題是,渲染函數(shù)常常包含大量的邏輯,最終看著更像是程序片斷(實(shí)際上就是)而不是界面的視覺(jué)呈現(xiàn)。對(duì)于部分開(kāi)發(fā)者來(lái)說(shuō),他們可能覺(jué)得這是個(gè)優(yōu)點(diǎn),但對(duì)那些像我一樣兼顧設(shè)計(jì)和開(kāi)發(fā)的人來(lái)說(shuō),模板能讓我們更好地在視覺(jué)上思考設(shè)計(jì)和 CSS。JSX 和 JavaScript 邏輯的混合干擾了我將代碼映射到設(shè)計(jì)的思維過(guò)程。相反,Vue.js 通過(guò)在模板中加入一個(gè)輕量級(jí)的 DSL (指令系統(tǒng)),換來(lái)一個(gè)依舊直觀的模板,且能將邏輯封裝進(jìn)指令和過(guò)濾器中。
React 的另一個(gè)問(wèn)題是:由于 DOM 更新完全交給 Virtual DOM 管理,當(dāng)想要自己控制 DOM 時(shí)就有點(diǎn)棘手了(雖然理論上可以做到,但是這樣做就本質(zhì)上違背了 React 的設(shè)計(jì)思想)。如果應(yīng)用需要特別的自定義 DOM 操作,特別是復(fù)雜時(shí)間控制的動(dòng)畫(huà),這個(gè)限制就很討厭。在這方面,Vue.js 更靈活,有許多用 Vue.js 制作的 FWA/Awwwards 獲獎(jiǎng)?wù)军c(diǎn)。
再多說(shuō)幾句:
React 團(tuán)隊(duì)雄心勃勃,計(jì)劃讓 React 成為通用平臺(tái)的 UI 開(kāi)發(fā)工具,而 Vue 專(zhuān)注于為 Web 提供實(shí)用的解決方案。
React,由于它的函數(shù)式特質(zhì),可以很好地使用函數(shù)式編程模式。但是對(duì)于初級(jí)開(kāi)發(fā)者和初學(xué)者這也導(dǎo)致較大的學(xué)習(xí)難度。Vue 更易學(xué)習(xí)并能快速投入開(kāi)發(fā)。
對(duì)于大型應(yīng)用,React 社區(qū)已經(jīng)創(chuàng)造了大量的狀態(tài)管理方案,例如 Flux/Redux。Vue 本身不解決這個(gè)問(wèn)題(React 內(nèi)核也是),但是可以輕松地修改狀態(tài)管理模式,實(shí)現(xiàn)一個(gè)類(lèi)似的架構(gòu)。Vue 有自己的狀態(tài)管理方案 Vuex,而且 Vue 也可以與 Redux 一起用。
Ember 是一個(gè)全能框架。它提供大量的約定,一旦你熟悉了它們,開(kāi)發(fā)會(huì)很高效。不過(guò),這也意味著學(xué)習(xí)曲線較高,而且不靈活。在框架和庫(kù)(加上一系列松散耦合的工具)之間權(quán)衡選擇。后者更自由,但是也要求你做更多的架構(gòu)決定。
也就是說(shuō),最好比較 Vue.js 內(nèi)核和 Ember 的模板與數(shù)據(jù)模型層:
Vue 在普通 JavaScript 對(duì)象上建立響應(yīng),提供自動(dòng)化的計(jì)算屬性。在 Ember 中需要將所有東西放在 Ember 對(duì)象內(nèi),并且手工為計(jì)算屬性聲明依賴(lài)。
Vue 的模板語(yǔ)法可以用全功能的 JavaScript 表達(dá)式,而 Handlebars 的語(yǔ)法和幫助函數(shù)語(yǔ)法相比之下非常受限。
Polymer 是另一個(gè)由 Google 支持的項(xiàng)目,實(shí)際上也是 Vue.js 的靈感來(lái)源之一。Vue.js 的組件可以類(lèi)比為 Polymer 中的自定義元素,它們提供類(lèi)似的開(kāi)發(fā)體驗(yàn)。最大的不同在于,Polymer 依賴(lài)最新的 Web 組件特性,在不支持的瀏覽器中,需要加載笨重的 polyfill,性能也會(huì)受到影響。相對(duì)的,Vue.js 無(wú)需任何依賴(lài),最低兼容到IE9。
另外,在 Polymer 1.0 中,為了性能開(kāi)發(fā)團(tuán)隊(duì)嚴(yán)格限制了它的數(shù)據(jù)綁定系統(tǒng)。例如,Polymer 模板支持的表達(dá)式僅有邏輯逆運(yùn)算和簡(jiǎn)單的方法調(diào)用。它的計(jì)算屬性實(shí)現(xiàn)得也不是很靈活。
最后,當(dāng)發(fā)布到生產(chǎn)環(huán)境時(shí),Polymer 元素需要用專(zhuān)用工具 vulcanizer 打包。相比之下,單文件 Vue 組件能與 Webpack 無(wú)縫整合,因而你可以輕松在組件中使用 ES6 及任意 CSS 預(yù)處理器。
Riot 2.0 提供類(lèi)似的基于組件的開(kāi)發(fā)模式(Riot 稱(chēng)之為“標(biāo)簽”),API 小而美。我認(rèn)為 Riot 與 Vue 在設(shè)計(jì)思路上有許多相同點(diǎn)。不過(guò),盡管比 Riot 重一點(diǎn),Vue 提供了一些顯著優(yōu)處: