
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實作快速渲染
- 輕量級
- 響應式元件
- 伺服器端渲染
- 易于內建路由工具,打包工具以及狀态管理工具
- 優秀的支援和社群