Reactjs vs. Vuejs

Reactjs vs. Vuejs
1 Star2 Stars3 Stars4 Stars5 Stars 給文章打分!
Loading...

歡迎大家關注騰訊雲技術社群-segmentfault官方主頁,我們將持續在部落格園為大家推薦技術精品文章哦~

紀俊,從事Web前端開發工作,2016年加入騰訊OMG廣告平臺產品部,喜歡研究前端技術框架。

這裡要討論的話題,不是前端框架哪家強,因為在 Vue 官網就已經有了比較全面客觀的介紹,並且是中文的。

上圖是二月份前端框架排名,React 位居第一,Vue 排名第三。還清晰記得,16 年十月份該 showcase 首頁並未看到 Vue,如今已有 40000 stars,那時的 React 也差不多這個成績,可見 Vue 2.0 有多受關注,而排名第二的 Angular 當時位居第一,短短數月 React、Vue 都有比較好的成績,而 Angular 的 stars 沒有明顯增長,是否可以斷章取義,Angular 正在慢慢地退出這個舞臺。

對於近期關注度最高的 React 和 Vue,想在這裡談談兩個框架在開發風格上的差異。Vue 升級到2.0之後新增了很多 React 原有的特性,我的理解是 Vue 在這些方面對 React 的肯定和致敬,下面將在幾個細節上作對比。

Vue更容易上手

Vue 更容易上手!這是真的嗎?我書讀的少,作者是想支援國產嗎?

Vue 的語法很自由,比如:

前期不需要認識複雜的生命週期函式,可能只關心 mounted 和 Vue.nextTick(保證 this.$el 在 document 中)

熟悉的前端模板

父子元件間通訊更靈活

slot,可以大尺度地擴充套件元件(但也不要過度使用哦)

v-model,mvvm 的方式處理表單更方便

官網中文文件(哈哈,不得不承認)

從入門學習一個框架的角度看,少一些規則多一些自由空間,門檻會低些。

表單在 React 中的蛋疼之處

React 和 Vue 如何拿 input 的 value,先上程式碼

Reactjs

class Demo extends React.Component{
constructor(props){
super(props)
this.state={
inputA: '',
inputB: ''
}
}
_onChangeA(e){
this.setState({
inputA: e.target.value
})
}
_onChangeB(e){
this.setState({
inputB: e.target.value
})
}
render() {
return (
<div>
<input 
onChange={this._onChangeA.bind(this)} 
value={this.state.inputA}
/>
<input 
onChange={this._onChangeB.bind(this)} 
value={this.state.inputB}
/>
</div>
);
}
};
ReactDOM.render(
<Demo/>,
document.getElementById('container')
);
###**Vuejs**
<div id="demo">
<input 
v-model="inputA"
:value="inputA"/>
<input 
v-model="inputB"
:value="inputB"
/>
<button
@click="show"
>
show
</button>
</div>
new Vue({
el: '#demo',
data: {
inputA: '',
inputB: ''
}
})

Vue 進行表單處理的方式是不是更簡潔,由於 v-model 屬性支援資料雙向繫結,說白了就是(value 的單向繫結 onChange 事件監聽)的語法糖,但這個味道還不錯吧,比起在 React 中需要繫結多個 onChange 事件確實要方便得多。

JSX vs Templates

剛接觸 React,因為用慣了javascript 模板引擎,一直堅信檢視與功能邏輯分離是正確的選擇,突然看到 JSX 把 html 寫在 js 裡,內心是拒絕的!

Facebook 官方好像知道大家對 JSX 有偏見,在文件一開始就給出解釋

We strongly believe that components are the right way to separate concerns rather than “templates” and “display logic.” We think that markup and the code that generates it are intimately tied together. Additionally, display logic is often very complex and using template languages to express it becomes cumbersome.

在這裡結合我的理解翻譯一下, React 團隊堅信一個元件的正確用途是 “separate concerns”,而不是前端模板或者展示邏輯。我們認為前端模板和元件程式碼是緊密相連的。另外,模板語言經常讓展示的邏輯變得更復雜。

剛開始沒弄明白什麼是 “separate concerns”,其實現在也… Facebook 可能是在強調元件應該從功能上去抽象定義,而不僅僅從視覺上區分。

看完官方答覆我欣然接受了,有誰在寫前端模板的時候,沒有摻雜業務邏輯的,摻雜了不就違背 MVC 嗎!Facebook 覺得這種“分離”讓問題更復雜,不如把模板和邏輯程式碼結合到一塊。而開發者一開始不接受 JSX,是受到傳統js拼接字串模板的死板方式影響,其實 JSX 更靈活,它在邏輯能力表達上完爆模板,但也很容易寫出凌亂的render函式,不如模板直觀
元件通訊

Vue 元件向上通訊可通過觸發事件,但在 Vue 2.0 廢棄 dispatch,建議使用global event bus。而大多初學者以為 React 只能靠呼叫父元件的 callback,並且這種方式遇到元件層次太深的時候簡直就是噩夢。其實 React 也可以通過事件通訊來解決問題,只不過需要額外 coding 或呼叫第三方外掛,而 Vue 的核心庫已實現了該功能。React 擁有豐富的生態圈,很多事情是大家一起完成的。

ref or props

父元件可通過 ref 定位子元件並呼叫它的 api,也可通過 props 傳遞資料,實現父元件通知子元件,ref 和 props 這兩種方式將決定元件的形態。在實際開發中,可能 Vue 先入為主,ref 也用的比較多,因為它在元件封裝力度上確實有優勢, api 可讓元件更抽象、更關注自身的功能,不受外界影響。而後來轉到 React 幾乎都是用 props 通訊,一開始還以為是 React 的問題,甚至還得出了這樣的結論:React 元件像是 UI 元件,Vue 元件更接近物件。直到最近看了 Facebook 文件,才發現另有蹊蹺。先看看之前用 Vue ,我是如何去建立一個列表(List)元件,並實現列表資料的新增和刪除,以及呼叫方式。

沒用過 ref 的同學,可以先看下文件,不過看完下面程式碼也能大概知道 ref 的作用。

Vuejs

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="demo">
<input
:value="input"
v-model="input"
/>
<button
@click="add"
>
add
</button>
<List
ref="list"
/>
</div>
var List = Vue.extend({
props: {
list: {
type: Array,
default: function(){return []}
}
},
template:'<div><ul v-for="(item, index) in list"><li>{{item.name}} <i @click="deleteItem(item, index)">delete</i></li></ul></div>',
data: function(){
return{
input: ''
}
},
methods: {
addItem: function(name){
this.list.push({name: name})
},
deleteItem: function(item, index){
this.list.splice(index, 1)
}
}
})
Vue.component('List',List)
new Vue({
el: '#demo',
data: {
input: ''
},
methods: {
add: function(){
this.$refs.list.addItem(this.input)
}
}
})

再看看 React 是怎麼做的

class List extends React.Component{
_delete(index){
this.props.onDelete && this.props.onDelete(index)
}
render() {
return (
<ul>
{
this.props.list.map((item, index)=>{
return (
<li 
key={index}
>
{item} 
<i onClick={this._delete.bind(this, index)}>
delete
</i>
</li>
)
})
}
</ul>
);
}
};
class Page extends React.Component{
constructor(props){
super(props)
this.state={
input: '',
list: []
}
}
_bindChange(e){
this.setState({
input: e.target.value
})
}
_add(){
this.state.list.push(this.state.input)
this.forceUpdate()
}
_delete(index){
this.state.list.splice(index, 1)
this.forceUpdate()
}
render() {
return (
<div>
<input
onChange={this._bindChange.bind(this)}
value={this.state.input}
/>
<button
onClick={this._add.bind(this)}
>
add
</button>
<List
list={this.state.list}
onDelete={this._delete.bind(this)}
/>
</div>
);
}
};
ReactDOM.render(
<Page/>,
document.getElementById('container')
);

通過上面兩段程式碼可以看出,在呼叫 List 元件的時候,React 比 Vue 複雜的多,不僅僅是多了 onChange,還有新增和刪除的邏輯,都必須在父元件中實現,這樣會導致專案中多處呼叫 List 元件,都必須實現這套相似的邏輯,而這套邏輯在 Vue 中已封裝在元件裡,這也是為什麼利用 ref 在封裝力度上有優勢,所以給我的感覺,React 比較關注元件的展示,而 Vue 比較關注功能。

細心的同學可能發現了,React也有 ref 屬性,它也可以讓父元件呼叫子元件的 api,但實際專案中卻很少看到,為什麼大家都這麼同步一致呢?我查了一下文件,原來 Facebook 不推薦過度使用 ref

Your first inclination may be to use refs to “make things happen” in your app. If this is the case, take a moment and think more critically about where state should be owned in the component hierarchy. Often, it becomes clear that the proper place to “own” that state is at a higher level in the hierarchy. See the Lifting State Up guide for examples of this.

官方還有個栗子,這裡我也舉個比較常見的

基於上面的栗子,比如現在列表資料多啦!需要在列表頂部顯示有多少條資料!我們可以定義一個顯示條數的元件 Counts。

Vuejs

var bus = new Vue()
var Counts = Vue.extend({
data: function(){
return{
count: 0
}
},
template: '<span>{{count}}</span>',
mounted: function(){
var self = this
bus.$on('plus', function(){
self.count  
})
bus.$on('minus', function(){
self.count--
})
}
})
Vue.component('Count', Count)
Reactjs
let Counts = (props)=>{
return (
<span>
{props.count}
</span>
);
}

如按照 Vue 的實現方法(好吧!這裡好像要黑 Vue,其實是我一開始的誤解),Counts 元件需監聽兩個事件(plus & minus),在事件回撥中去更新條數,當 List 進行add() 或 delete() 需觸發plus / minus,且不說 Counts 元件複雜,這事件流也很難追溯,程式碼放久看著吃力!但 React 把共享資料抽離了,父元件把this.state.list.length通過 props 傳入 Counts,這種方式邏輯更清晰,擴充套件能力更強。雖然像 React 這種,在不需要元件共享資料時,呼叫起來很繁瑣,呼叫 List 時add / delete 邏輯都要寫一遍,但業務的發展很難說,很多意想不到的情況都會發生,比如上面的栗子,後期指不定還要加一個分頁元件呢,所以我懸崖勒馬,以後不管在 Vue 還是 React,儘量少用 ref 呼叫子元件。當元件之間有共享資料時,該資料與操作該資料的邏輯,應該放在最接近它們的父元件,這樣元件的邏輯會更合理,更清晰!

最後,這兩個框架的路線有差異,Vue 偏向大而全,把很多特性都封裝進核心庫,React 則不同,React 核心庫只是 React 生態圈很小一部分,只負責 view 這個層面,其它事情都是由大家一起完成,所以 React 會有這麼多外掛。Reactjs 和 Vuejs 都是偉大的框架!

歡迎加入QQ群:374933367,與騰雲閣原創作者們一起交流,更有機會參與技術大咖的線上分享!

相關閱讀

Vue.js前後端同構方案之準備篇——程式碼優化
Vue.js 實戰總結
React 同構思想

此文已由作者授權騰訊雲技術社群釋出,轉載請註明文章出處
原文連結:https://www.qcloud.com/commun…
獲取更多騰訊海量技術實踐乾貨,歡迎大家前往騰訊雲技術社群

相關文章

前端開發 最新文章