對比其他框架
这个页面无疑是最难编写的,但我们认为它也是非常重要的。或许你曾遇到了一些问题并且已经用其他的框架解决了。你来这里的目的是看看 Vue 是否有更好的解决方案。这也是我们在此想要回答的。
客观来说,作为核心团队成员,显然我们会更偏爱 Vue,认为对于某些问题来讲用 Vue 解决会更好。如果没有这点信念,我们也就不会整天为此忙活了。但是在此,我们想尽可能地公平和准确地来描述一切。其他的框架也有显著的优点,例如 React 庞大的生态系统,或者像是 Knockout 对浏览器的支持覆盖到了 IE6。我们会尝试着把这些内容全部列出来。
我们也希望得到你的帮助,来使文档保持最新状态,因为 JavaScript 的世界进步的太快。如果你注意到一个不准确或似乎不太正确的地方,请提交问题让我们知道。
目录
React
React 和Vue 有許多相似之處,它們都有:
使用Virtual DOM
提供了響應式(Reactive) 和元件化(Composable) 的檢視元件。
將注意力集中保持在核心庫,而將其他功能如路由和全域狀態管理交給相關的庫。
由於有著眾多的相似處,我們會用更多的時間在這一塊進行比較。這裡我們不只保證技術內容的準確性,同時也兼顧了平衡的考量。我們需要承認 React 比 Vue 更好的地方,例如更豐富的生態系統。
下列部分章節會略微有些過時,因為最近 React 16 的發布,我們計劃在不久的將來和 React 社群一起重寫這部分內容。
運行時效能
#React 和Vue 都是非常快的,所以速度並不是在它們之中做選擇的決定性因素。對於具體的資料表現,可以移步這個第三方 benchmark,它專注於渲染/更新非常簡單的元件樹的真實效能。
優化
在 React 應用程式中,當某個元件的狀態改變時,它會以該元件為根,重新渲染整個元件子樹。
如要避免不必要的子元件的重渲染,你需要在所有可能的地方使用 PureComponent
,或手動實作 shouldComponentUpdate
方法。同時你可能會需要使用不可變的資料結構來讓你的元件更容易被最佳化。
然而,使用 PureComponent
和 shouldComponentUpdate
時,需要確保元件的整個子樹的渲染輸出都是由該元件的 props 決定的。如果不符合這個情況,那麼此類最佳化就會導致難以察覺的渲染結果不一致。這使得 React 中的組件優化伴隨著相當的心智負擔。
在 Vue 應用程式中,元件的依賴是在渲染過程中自動追蹤的,所以系統能精確知道哪個元件確實需要被重渲染。你可以理解為每一個元件都已經自動獲得了 shouldComponentUpdate
,並且沒有上述的子樹問題限制。
Vue 的這個特點使得開發者不再需要考慮此類最佳化,從而能夠更好地專注於應用程式本身。
HTML & CSS
#在 React 中,一切都是 JavaScript。不只是 HTML 可以用 JSX 來表達,現在的潮流也越來越多地將 CSS 也納入 JavaScript 來處理。這類方案有其優點,但也存在一些不是每個開發者都能接受的取捨。
Vue 的整體思想是擁抱經典的 Web 技術,並在其上擴展。我們下面會詳細分析一下。
JSX vs Templates
在 React 中,所有的元件的渲染功能都依賴 JSX。 JSX 是使用 XML 語法編寫 JavaScript 的一種語法糖。
使用 JSX 的渲染函數有以下這些優點:
你可以使用完整的程式語言 JavaScript 功能來建立你的視圖頁面。例如你可以使用臨時變數、JS 自帶的流程控制、以及直接引用目前 JS 作用域中的值等等。
開發工具對 JSX 的支援相比於現有可用的其他 Vue 範本還是比較先進的 (比如,linting、型別檢查、編輯器的自動完成)。
事實上 Vue 也提供了 渲染函數,甚至支援 JSX。然而,我們預設推薦的還是模板。任何合乎規範的HTML 都是合法的Vue 模板,這也帶來了一些特有的優勢:
對於許多習慣了HTML 的開發者來說,模板比起JSX 讀寫起來更自然。這裡當然有主觀偏好的成分,但如果這種差異會導致開發效率的提升,那麼它就有客觀的價值存在。
基於 HTML 的範本使得將現有的應用程式逐步遷移到 Vue 更為容易。
這也使得設計師和新人開發者更容易理解和參與專案。
你甚至可以使用其他模板預處理器,例如 Pug 來書寫 Vue 的模板。
有些開發者認為模板意味著需要學習額外的 DSL (Domain-Specific Language 領域特定語言) 才能進行開發-我們認為這種差異是比較膚淺的。首先,JSX 並不是沒有學習成本的——它是基於 JS 之上的一套額外語法。同時,就像熟悉 JS 的人學習 JSX 會很容易一樣,熟悉 HTML 的人學習 Vue 的模板語法也是很容易的。最後,DSL 的存在使得我們可以讓開發者用更少的程式碼做更多的事,例如v-on
的各種修飾符,在JSX 中實現對應的功能會需要多得多的代碼。
更抽像一點來看,我們可以把元件區分為兩類:一類是偏視圖表現的 (presentational),一類則是偏邏輯的 (logical)。我們推薦在前者中使用模板,在後者中使用 JSX 或渲染函數。這兩類元件的比例會根據應用類型的不同而變化,但整體來說我們發現表現類別的元件遠遠多於邏輯類別元件。
元件作用域內的 CSS
除非你把元件分佈在多個檔案上(例如CSS Modules),CSS 作用域在React 中是透過CSS-in-JS 的方案實現的(例如styled-components 、glamorous 和emotion)。這引入了一個新的以元件為導向的樣式範例,它和普通的 CSS 撰寫過程是有區別的。另外,雖然在建置時將 CSS 提取到一個單獨的樣式表是支援的,但 bundle 裡通常還是需要一個執行時間程式來讓這些樣式生效。當你能夠利用 JavaScript 靈活處理樣式的同時,也需要權衡 bundle 的尺寸和運行時的開銷。
如果你是CSS-in-JS 的愛好者,許多主流的CSS-in-JS 函式庫也都支援Vue (例如styled-components-vue 和vue -emotion)。這裡 React 和 Vue 主要的區別是,Vue 設定樣式的預設方法是單一檔案元件裡類似 style
的標籤。
單一檔案元件讓你可以在同一個檔案裡完全控制 CSS,並將其作為元件程式碼的一部分。
<style scoped> @media (min-width: 250px) { .list-container:hover { background: orange; } } </style>
這個可選scoped
屬性會自動加入一個唯一的屬性(例如data-v-21e5b78
) 為元件內CSS 指定作用域,編譯的時候.list-container:hover
會被編譯成類似.list-container[data-v-21e5b78]:hover
。
最後,Vue 的單一檔案元件裡的樣式設定是非常靈活的。透過vue-loader,你可以使用任意預處理器、後處理器,甚至是深度整合CSS Modules——全部都在<style>
標籤內。
規模
#向上擴展
##Vue 和React 都提供了強大的路由來應對大型應用。 React 社群在狀態管理方面非常有創新精神 (例如 Flux、Redux),而這些狀態管理模式甚至Redux 本身 也可以非常容易的整合在 Vue 應用中。實際上,Vue 更進一步地採用了這種模式 (Vuex),更深入整合 Vue 的狀態管理解決方案 Vuex 相信能為你帶來更好的開發體驗。
兩者另一個重要差異是,Vue 的路由庫和狀態管理庫都是由官方維護支援且與核心庫同步更新的。 React 則是選擇把這些問題交給社區維護,因此創造了一個更分散的生態系統。但相對的,React 的生態系統相比 Vue 更繁榮。
最後,Vue 提供了 CLI 鷹架,能讓你透過互動式的鷹架引導非常容易建立專案。你甚至可以使用它快速開發元件的原型。 React 在這方面也提供了create-react-app,但現在還存在一些限制:
它不允許在專案產生時進行任何配置,而Vue CLI 運行於可升級的運行時依賴之上,該運行時可以透過插件進行擴展。
它只提供一個建立單頁面應用程式的預設選項,而 Vue 提供了各種用途的範本。
它不能用使用者自建的 預設配置 建置項目,這對企業環境下預先建立約定是特別有用的。
而要注意的是這些限制是故意設計的,這有它的優點。例如,如果你的專案需求非常簡單,你就不需要自訂生成流程。你能把它當作一個依賴來更新。如果閱讀更多關於不同的設計理念。
向下擴展
React 學習曲線陡峭,在你開始學習 React 之前,你需要知道 JSX 和 ES2015,因為許多範例用的是這些語法。你需要學習建置系統,雖然你在技術上可以用 Babel 即時編譯程式碼,但這並不建議用於生產環境。
就像 Vue 向上擴展好比 React 一樣,Vue 向下擴展後就類似於 jQuery。只要把如下標籤放到頁面就可以運行:
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
然後你就可以寫Vue 程式碼並應用到生產中,你只要用min 版Vue 檔案替換掉就不用擔心其他的效能問題。
由於起步階段不需學 JSX,ES2015 以及建置系統,所以開發者只需不到一天的時間閱讀指南就可以建立簡單的應用程式。
原生渲染
#React Native 能讓你用相同的元件模型寫一個有本地渲染能力的 APP (iOS 和 Android)。能同時跨多平台開發,對開發者來說是非常棒的。相應地,Vue 和Weex 會進行官方合作,Weex 是阿里巴巴發起的跨平台使用者介面開發框架,同時也正在Apache 基金會進行專案孵化,Weex 允許你使用Vue 語法開發不僅僅可以運行在瀏覽器端,還能用來開發iOS 和Android 上的原生應用的元件。
在現在,Weex 還在積極發展,成熟度也無法和 React Native 競爭。但是,Weex 的發展是由世界上最大的電子商務企業的需求在驅動,Vue 團隊也會和 Weex 團隊積極合作確保為開發者帶來良好的開發體驗。
另一個選擇是 NativeScript-Vue,一個用 Vue.js 建立完全原生應用程式的 NativeScript 外掛程式。
MobX
Mobx在React 社群中很流行,實際上在Vue 也採用了幾乎相同的反應系統。在有限程度上,React Mobx 也可以被認為是更繁瑣的 Vue,所以如果你習慣組合使用它們,那麼選擇 Vue 會更合理。
Preact 和其它類別React 函式庫
類別React 的函式庫們往往盡可能地與React共享API 和生態。因此上述比較對它們來說也同樣適用。它們和 React 的不同往往在於較小的生態。因為這些函式庫無法 100% 相容於 React 生態中的全部,部分工具和輔助函式庫也可能無法使用。或者即使看起來能工作,但也有可能隨時發生不相容,除非你用的這個類 React 庫官方與 React 保持嚴格一致。
AngularJS (Angular 1)
Vue 的一些語法和AngularJS 的很相似(例如v-if
vs ng-if
)。因為 AngularJS 是 Vue 早期開發的靈感來源。然而,AngularJS 中存在的許多問題,在 Vue 中已經解決。
#複雜性
#在API 與設計兩方面上Vue.js 都比AngularJS 簡單得多,因此你可以快速地掌握它的全部特性並投入開發。
靈活性與模組化
#Vue.js 是一個更靈活開放的解決方案。它允許你以希望的方式組織應用程序,而不是在任何時候都必須遵循 AngularJS 制定的規則,這讓 Vue 能適用於各種專案。我們知道把決定權交給你是非常必要的。
這也是為什麼我們提供了一個基於 Vue.js 進行快速開發的完整系統。 Vue CLI 旨在成為 Vue 生態系統中標準的基礎工具。它使得多樣化的建置工具透過妥善的預設配置無縫協作在一起。這樣你就可以專注在應用程式本身,而不會在配置上花費太多時間。同時,它也提供了根據實際需求調整每個工具配置的靈活性。
資料綁定
#AngularJS 使用雙向綁定,Vue 在不同元件間強制使用單向資料流。這使得應用程式中的資料流更加清晰易懂。
指令與元件
#在 Vue 中指令和元件分得更清晰。指令只封裝 DOM 操作,而元件代表一個自給自足的獨立單元-有自己的視圖和資料邏輯。在 AngularJS 中,每件事都由指令來做,而元件只是一種特殊的指令。
運行時效能
#Vue 有更好的效能,而且非常非常容易最佳化,因為它不使用髒檢查。
在 AngularJS 中,當 watcher 越來越多時會變得越來越慢,因為作用域內的每一次變化,所有 watcher 都要重新計算。並且,如果一些 watcher 觸發另一個更新,髒檢查循環 (digest cycle) 可能要運行多次。 AngularJS 使用者常常要使用深奧的技術,以解決髒檢查循環的問題。有時沒有簡單的辦法來優化有大量 watcher 的作用域。
Vue 則根本沒有這個問題,因為它使用基於依賴追蹤的觀察系統並且非同步佇列更新,所有的資料變化都是獨立觸發,除非它們之間有明確的依賴關係。
有趣的是,Angular 和 Vue 用相似的設計解決了一些 AngularJS 中存在的問題。
Angular (原本的Angular 2)
我們將新的Angular 獨立開來討論,因為它是一個和AngularJS 完全不同的框架。例如:它具有優秀的元件系統,而且許多實作已經完全重寫,API 也完全改變了。
#TypeScript
#Angular 事實上必須用 TypeScript 來開發,因為它的文檔和學習資源幾乎全部都是面向 TS 的。 TS 有許多好處-靜態型別檢查在大規模的應用中非常有用,同時對於 Java 和 C# 背景的開發者也是非常提升開發效率的。
然而,並不是所有人都想用 TS——在中小型規模的專案中,引入 TS 可能並不會帶來太多明顯的優勢。在這些情況下,使用 Vue 會是更好的選擇,因為在沒有 TS 的情況下使用 Angular 會很有挑戰性。
最後,雖然Vue 和TS 的整合可能不如Angular 那麼深入,我們也提供了官方的類型聲明 和組件裝飾器,並且知道有大量用戶在生產環境中使用Vue TS 的組合。我們也和微軟的 TS / VSCode 團隊進行積極的合作,目標是為 Vue TS 使用者提供更好的類型檢查和 IDE 開發體驗。
運行時效能
#這兩個框架都很快,有非常類似的benchmark 數據。你可以瀏覽特定的數據做更細粒度的對比,不過速度應該不是決定性的因素。
體積
#在體積方面,最近的Angular 版本中在使用了AOT 和tree-shaking 技術後使得最終的程式碼體積減少了許多。但即使如此,一個包含了 Vuex Vue Router 的 Vue 項目 (gzip 之後 30kB) 相比使用了這些優化的 angular-cli
生成的默認項目尺寸 (~65KB) 還是要小得多。
靈活性
#Vue 相比於Angular 更加靈活,Vue 官方提供了構建工具來協助你建立項目,但它不會限制你去如何組織你的應用程式碼。有人可能喜歡有嚴格的程式碼組織規範,但也有開發者喜歡更靈活自由的方式。
學習曲線
#要學習 Vue,你只需要有好的 HTML 和 JavaScript 基礎。有了這些基本的技能,你就可以非常快速地透過閱讀 指南 投入開發。
Angular 的學習曲線是非常陡峭的——作為一個框架,它的 API 面積比起 Vue 要大得多,你也因此需要理解更多的概念才能開始有效率地工作。當然,Angular 本身的複雜度是因為它的設計目標就是只針對大型的複雜應用;但不可否認的是,這也使得它對經驗不甚豐富的開發者相當的不友善。
Ember
#Ember 是一個全能框架。它提供了大量的約定,一旦你熟悉了它們,開發會變得很有效率。不過,這也意味著學習曲線較高,而且不靈活。這意味著在框架和函式庫 (加上一系列鬆散耦合的工具) 之間做權衡選擇。後者會比較自由,但也要求你做更多架構上的決定。
也就是說,我們最好比較的是Vue 核心和Ember 的模板與資料模型層:
Vue 在普通JavaScript 物件上建立回應,提供自動化的計算屬性。在 Ember 中需要將所有東西放在 Ember 物件內,並且手動為計算屬性聲明依賴。
Vue 的模板語法可以用全功能的 JavaScript 表達式,而 Handlebars 的語法和幫助函數相比來說非常受限。
在性能上,Vue 比 Ember 好很多,即使是 Ember 3.x 的最新 Glimmer 引擎。 Vue 能夠自動批次更新,而 Ember 在效能敏感的場景時需要手動管理。
Knockout
Knockout 是MVVM 領域內的先驅,並且追蹤依賴。它的響應系統和 Vue 也很相似。它在瀏覽器支援以及其他方面的表現也是令人印象深刻的。它最低能支援到 IE6,而 Vue 最低只能支援到 IE9。
隨著時間的推移,Knockout 的發展已放緩,並且略顯有點老舊了。例如,它的元件系統缺少完備的生命週期事件方法,儘管這些在現在是非常常見的。以及相較於 Vue 呼叫子元件的介面它的方法顯得有點笨重。
如果你有興趣研究,你也會發現二者在介面設計的概念上是不同的。這可以透過各自創建的 simple Todo List 體現出來。或許有點主觀,但很多人認為 Vue 的 API 介面更簡單結構更優雅。
Polymer
Polymer 是另一個由Google贊助的項目,事實上也是 Vue 的靈感來源。 Vue 的元件可以粗略的類比於 Polymer 的自訂元素,並且兩者俱有相似的開發風格。最大的不同之處在於,Polymer 是基於最新版的 Web Components 標準之上,並且需要重量級的 polyfills 來幫助工作 (效能下降),而瀏覽器本身並不支援這些功能。相較而言,Vue 在支援到 IE9 的情況下並不需要依賴 polyfills 來工作。
在 Polymer 版本中,為了彌補效能,團隊非常有限的使用資料綁定係統。例如,在 Polymer 中唯一支援的表達式只有布林值否定和單一的方法調用,它的 computed 方法的實作也並不是很靈活。
Riot
#Riot 3.0 提供了一個類似於基於元件的開發模型(在Riot 中稱之為Tag),它提供了小巧精美的API。 Riot 和 Vue 在設計概念上可能有許多相似性。儘管比起 Riot ,Vue 要顯得重一點,Vue 還是有很多顯著優勢的:
更好的效能。 Riot 使用了 遍歷 DOM 樹 而不是虛擬 DOM,但實際上使用的還是髒檢查機制,因此和 AngularJS 患有相同的效能問題。
更多成熟工具的支援。 Vue 提供官方支援 webpack 和 Browserify,而 Riot 是依靠社群來建立整合系統。