2016年,React在Web端和移動端都實現了迅速的成長,穩穩地領先於其主要競爭對手Augular,鞏固了其作為前端框架之王的地位。
但是Vue在這一年里的表現也可謂同樣的耀眼。Vue.js 2.0 的發布在整個JavaScript社區都引起了巨大反響,這一點僅從它在Github中漲了25,000顆star,就足以得到證明。
不得不說React和Vue的使用范圍是相似的:都是基於組件化的輕量級框架,都專注於構建用戶界面的視圖層;都既可以用於簡單的項目,也適用於使用前沿技術的大規模復雜項目。
因此,很多Web開發者都難免糾結到底要從中選擇哪一個框架。這兩者中能否分出個高下好壞?或者它們各自有哪些優缺點是需要我們注意的?還是說它們實際上差不多,用誰都一樣?
兩種框架,兩個擁護者
在這篇文章中我想用盡可能公平,全面的對比來回答這些疑問。但是問題來了:我是個不折不扣的Vue迷弟,肯定會偏向它。今年我在項目中大量地使用了Vue,在Medium上安利它的好處,甚至還在Udemy開設了一門關於Vue的入門課程。
為了平衡一下,我邀請了我的朋友Alexis Mangin一起參與討論。他是一名優秀的Javascript開發者,且是React的鐵粉。與我相似的是,他也頻繁地在各種項目中(包括Web端和移動端項目)使用着React。
有一天他問我說:“為什么你這么喜歡用Vue,而不是React?”,當時由於我不太了解React,所以很難給出一個很好的回答。於是我向他提議,我們找一天帶上各自的筆記本電腦,一起探討我們各自喜愛的框架的好處。
Anthony(左)和 Alexis(右)在泰國清邁的Bull and Bear咖啡館里比較React和Vue
經過大量地討論和互相學習,我們得出了以下六個關鍵點:
如果你喜歡用(或希望能夠用)模板搭建應用,請使用Vue
Vue應用的默認選項是把markup放入HTML文件中。數據綁定表達式使用的是與Angular相似的雙大括號(moustache)語法,而指令(特殊的HTML屬性)則用於向模板中添加功能。
下面是一個簡單的Vue應用示例。它會展示一條消息(message),和一個用來動態反轉這條消息的按鈕:
// HTML
-
<div id="app">
-
<p>{{ message }}</p>
-
<button v-on:click="reverseMessage">Reverse Message</button>
-
</div>
// JS
-
new Vue({
-
el: '#app',
-
data: {
-
message: 'Hello Vue.js!
-
},
-
methods: {
-
reverseMessage: function () {
-
this.message = this.message.split('').reverse().join('');
-
}
-
}
-
});
-
React應用則與之相反,不使用模板,而是要求開發者借助JSX在JavaScript中創建DOM。下面是用React實現的相同的應用:
// HTML
<div id="app"></div>
// JS (pre-transpilation)
-
class App extends React.Component {
-
constructor(props) {
-
super(props);
-
this.state = {
-
message: 'Hello React.js!'
-
};
-
}
-
reverseMessage() {
-
this.setState({
-
message: this.state.message.split('').reverse().join('')
-
});
-
}
-
render() {
-
return (
-
<div>
-
<p>{this.state.message}</p>
-
<button onClick={() => this.reverseMessage()}>
-
Reverse Message
-
</button>
-
</div>
-
)
-
}
-
}
ReactDOM.render(App, document.getElementById('app'));
對於來自標准Web開發的新開發者來說,模板更容易理解。然而甚至連一些資深的開發者也喜歡使用模板,因為模板能更好地把功能和布局分割開來,還為使用Pug之類的模板引擎提供了可能。
不過使用模板的代價在於你需要學習所有的HTML擴展語法,而渲染函數(render function)只要求會使用標准的HTML和JavaScript。而且比起模板,渲染函數更易於調試和測試。但是,你並不應該因此就錯過Vue,因為在Vue2.0中已經提供了使用模板或者渲染函數的選項。
如果你喜歡簡單和“能用就行”的東西,請使用Vue
一個簡單的Vue項目能不需要轉譯直接使用在瀏覽器中,這使得在項目中使用Vue可以像使用jQuery一樣容易。當然這對於React來說在技術上也是可行的,但典型的React代碼是更多地依賴於JSX和諸如class等ES6特性的。而Vue的簡單則是更深層地源於其設計的。讓我們來比較一下這兩個框架是如何處理應用數據的(即“state”):
React里的狀態(state)是不可變(immutable)的,因此你不能直接地改變它,而是要用setState API方法:
-
this.setState({
-
message: this.state.message.split('').reverse().join('')
-
});
React是通過比較當前狀態和前一個狀態的區別來決定何時及如何重新渲染DOM的內容,因此需要使用不可變的狀態。
而與此相反的是,Vue中的數據是可變的(mutated),所以同樣的數據變量可以用簡潔得多的方式修改:
-
// Note that data properties are available as properties of
-
// the Vue instance
this.message = this.message.split('').reverse().join('');
讓我們來看看Vue中是如何對狀態進行管理的:當你向狀態中添加一個新對象時,Vue將遍歷其中的所有屬性並且將它們轉換為getter,setter方法。於是Vue的響應系統開始保持對該狀態的跟蹤,當該狀態的內容發生變化的時候就會自動重新渲染DOM。令人佩服的是,Vue中改變狀態的操作不僅更加簡潔,而且它的重新渲染系統實際上比React的更快更高效。
不過Vue的響應系統還是有些坑的,比如它無法檢測屬性的添加和刪除,以及某些數組更改。這時候就要用Vue API中的類似於React的set方法的措施來解決。
如果你的應用需要盡可能的小和快,請使用Vue
當應用程序的狀態改變時,React和Vue都會構建一個虛擬DOM並同步到真實DOM中。兩者都有它們各自的優化這個過程的方式。
Vue的核心開發者提供了一個benchmark測試,來表明Vue的渲染系統比React的更快,具體基准的設定以及同其他框架的比較詳見vuejs.org。測試方法是將含有10000個項目的列表渲染100次,結果如下圖。
從實用的角度來看,這種benchmark只跟邊緣情況有關,而大部分應用程序中不會經常進行這種操作,所以這不應該被視作一個重要的比較點。但是,頁面大小則是與所有項目有關的,這方面Vue又一次優於React,它目前的版本壓縮后只有25.6KB。要用React實現同樣的功能,你需要React DOM(37.4KB)和React with Addon庫(11.4KB),共計44.8KB,幾乎是Vue的兩倍大。雖然從React你的確會得到更豐富的API,但雙倍的體積並不能帶來雙倍的功能。
如果你計划構建一個大型應用程序,請使用React
像文章開頭那樣,用Vue和React實現的簡單應用程序來比較兩者,可能會讓一個開發者從一開始就更傾向於Vue。這是因為基於模板的應用程序乍看上去更易理解,而且能很快地寫好並跑起來。但是這些最初的便利會引入技術債並阻礙應用擴展到更大的規模。模板容易出現難以注意到的運行時錯誤,同時也不易於測試,重構和分解。
相比之下,Javascript模板可以組織成經過良好分解,且使用DRY(don't repeat yourself - 避免重復代碼)原則的代碼的組件,因而具有更強的可重用性和可測試性。Vue也有組件系統和渲染函數,但React的渲染系統可配置性更強,並包含如shallow rendering這樣的特性,可結合React的測試工具一起使用,從而大為提高代碼的可測試性及可維護性。
雖然React的不可變(immutable)應用狀態寫起來可能不夠Vue簡潔,但它在大型應用中仍會大放異彩,因為透明度和可測試性此時變得至關重要。
如果你想要一個同時適用於Web端和原生App的框架,請選擇React
React Native是一個用於通過Javascript構建移動端原生應用程序的庫。 它與React.js相同,只是不使用Web組件,而是使用原生組件。 如果你學過React.js,很快就能上手React Native,反之亦然。
// JS
-
import React, { Component } from 'react';
-
import { AppRegistry, Text, View } from 'react-native';
-
class HelloWorld extends Component {
-
render() {
-
return (
-
<View>
-
<Text>Hello, React Native!</Text>
-
</View>
-
);
-
}
-
}
AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
其意義在於,開發者只需要一套知識和工具就能開發Web應用和移動端原生應用。如果你想同時做Web端開發和移動端開發,學習React對你來說是相當划算的。
阿里的Weex也是一個跨平台UI項目,目前它以Vue為靈感,使用了許多相同的語法,並計划未來實現完全集成Vue,不過集成的時間和具體細節還未確定。由於Vue的設計中將HTML模板作為其核心部分之一,並且現有特性不支持自定義渲染,因此以Vue.js目前的形態來說,很難看到Weex與之的關系將能像React和React Native一樣緊密。
如果你想要最大的生態圈,請使用React
毫無疑問,React目前比Vue要受歡迎許多——它在NPM上每個月的下載量約為250萬次,而Vue只有22.5萬次。
人氣帶來的好處不僅是表面上的名聲,還意味着更多相關的技術文章,教程和更多Stack Overflow上的解答和幫助;以及有着更多的工具和插件可以在項目中使用,開發者不用從零開始,可以省很多力氣。
這兩個框架都是開源的,但是React誕生於Facebook,自帶給力的資助,它的開發者和Facebook都承諾會持續維護React。而Vue則是由獨立開發者尤雨溪創造,目前也只有他一名全職維護者。雖然也有一些公司資助Vue,但是規模和Facebook和Google沒得比。
不過由於Vue的團隊的努力,它的小規模和獨立性並沒有成為劣勢。Vue有着固定的發布周期,甚至更令人稱道的是,Github上Vue只有54個待解決問題(open issue),已關閉問題(closed issue)則有3456個;與之相比,React的已關閉問題數目相差不多(3447個),待解決問題卻有多達530個。
如果你已經對其中一個用得滿意了,就沒有必要換了
總結一下,我們發現,Vue的優勢包括:
-
模板和渲染函數的彈性選擇
-
簡單的語法及項目創建
-
更快的渲染速度和更小的體積
React的優勢包括:
-
更適用於大型應用和更好的可測試性
-
同時適用於Web端和原生App
-
更大的生態圈帶來的更多支持和工具
而實際上,React和Vue都是非常優秀的框架,它們之間的相似之處多過不同之處,並且它們大部分最棒的功能是相通的:
-
利用虛擬DOM實現快速渲染
-
輕量級
-
響應式組件
-
服務器端渲染
-
易於集成路由工具,打包工具以及狀態管理工具
-
優秀的支持和社區