【前端前沿看點】深度本質分析對比weex和react native
前言
weex的思想是多個平臺,只寫一套程式碼,而react-native的思想是多個平臺可以寫多套程式碼,但其使用的是同一套語言框架。
weex的目標在於抹平各個平臺的差異性,從而簡化應用開發。而react-native承認了各個平臺之間的差異,退而求其次,在語言和框架層面對平臺進行抽象,從方法論的角度去解決多平臺開發的問題。
進一步瀏覽weex和react-native的程式碼之後,可以得出如下的公式。
weex = Vue.js + H5/Native
react-native = React + Native
總的來說,其差異性如下表格所示。
dimension | weex | react-native |
---|---|---|
js framework | Vue.js | React |
principle | write once, run anywhere | learn once, write anywhere |
個人觀點,weex和react-native最核心的區別就是這兩個。然而就只這兩個維度的同步,導致了weex和react-native完全不一樣的發展方向。
Vue.js vs React
維度 | Vue.js | React |
---|---|---|
定位 | UI框架 | UI框架 |
目標平臺 | Web | 多平臺 |
架構 | MVVM | React |
資料流 | 資料繫結 | 單向資料流動 |
元件系統 | 有 | 有 |
響應式 | 是 | 否 |
開發語言 | html/css/js | all in js |
flexbox | 支援 | 支援 |
外圍框架 | 能和其他js框架整合使用 | 能和其他js框架整合使用 |
渲染機制 | real DOM | Virtual DOM |
動畫 | 支援 | 支援 |
級別 | 輕量級 | 重量級 |
weex vs react-native
維度 | weex | react-native |
---|---|---|
思想 | write once, run anywhere | learn once, write anywhere |
試用場景 | 簡單明瞭 | 難易雙修 |
擴充套件 | 為了保證各平臺的一致性,一次擴充套件得在各個平臺都實現 | 不同平臺可自由擴充套件 |
社群 | 內測開源 | 15年3月開源,社群非常活躍 |
支援 | alibaba支援 | facebook支援 |
元件豐富程度 | 基本只有自帶的10餘種 | 除了自帶的,還有js.coach上社群貢獻的,還是比較豐富的 |
上手難度 | 容易 | 困難 |
調式 | 暫時log除錯 | 有專門的除錯工具,chrome除錯,較為完善 |
IDE | 文字編輯器 | Nuclide/文字編輯器 |
Vue.js
Vue.js雖然是Evan You個人開發的開源專案,其社群活躍度以及程式碼質量還是值得一提的。在寫此文章之際,Vue.js在Github上的Star達到了21099,Fork達到了2186。雖然相比於react的Star數44108,Fork數7610還有一定距離,但考慮到作為個人開發者能有如此多的人關注參與,該框架的優秀程度恐怕不會低於React。
Vue.js的文件資料非常齊全,而且其本身的設計非常簡潔,因此絕大部分開發者只要花費少量的時間就能快速上手Vue.js。其中VUE.JS: A (RE)INTRODUCTION是 Vue.js的作者Evan You對Vue.js的介紹,非常值得一看。我想這可能也是weex團隊選擇Vue.js入手的原因之一吧。對Vue.js有興趣的同學可以移步Vue.js Guide自行學習。
Vue.js用來構建互動式web介面的,其主要的關注點和React是一樣的,都是立足於View層。
Vue.js最核心的部分是兩個Reactive Data Binding以及Composable View Components。還值得特別關注的是,其保留了html、css、js分離的寫法,使得現有的前端開發者在開發的時候能保持原有的習慣。
響應式資料繫結
Vue.js將介面開發分成了三個部分,分別是View、ViewModel和Model,這種劃分在客戶端開發看來是非常合理的,也經過了實際的檢驗。以HelloWorld為例來說明,示例來源Vue.js Guide。
<!-- this is our View -->
<div id="example-1">
Hello {{ name }}!
</div>
<!-- this is our Model -->
var exampleData = {
name: 'Vue.js'
}
<!-- this is our ViewModel -->
var exampleVM = new Vue({
el: '#example-1',
data: exampleData
})
這就是經典的MVVM模式,Vue.js通過極簡的API,將資料和檢視繫結在一起,也就是所謂的Data-Binding。
這樣,當資料變化的時候,介面就能變化,實現了資料驅動的響應式變成。
元件化
當我們在寫網頁的時候,本質上就是構造DOM樹,DOM樹則是由div、span等元素組成的。div、span這樣的元素是構建大型應用的基礎。其實Vue.js或者其他的UI框架基本也是一樣的,他們都會提供自己的元件系統。這些元件就類似div元素,一般具有一下特徵:
- 小巧精緻
- 能重用
- 自包含,高內聚
當我們使用Vue.js開發應用的時候,就是搭建特定的元件樹。這些元件可以是Vue.js定義的,也可以是開發者自己定義的,這非常重要。
看個元件化的例子。
// example元件定義
var Example = Vue.extend({
template: '<div>{{ message }}</div>',
data: function () {
return {
message: 'Hello Vue.js!'
}
}
})
// register it with the tag <example>
Vue.component('example', Example)
// example元件使用
<example></example>
元件間資料傳遞
Vue.js的元件都是有自己獨立的scope的,因此子元件是不能直接訪問到父元件的資料的。資料一般都是通過props來傳遞的,示例說明。
// define component
Vue.component('child', {
// declare the props
props: ['msg'],
// the prop can be used inside templates, and will also
// be set as `this.msg`
template: '<span>{{ msg }}</span>'
})
// usage
<child msg="hello!"></child>
上述方式只能實現元件樹從上往下傳遞資料,在Vue.js中,會有大量的場景需要子元件向父元件傳輸資料,甚至兄弟元件之間傳遞資料,一般這種時候就需要使用以下幾種能力。
- 子元件獲取父元件的能力(
this.$parent
) - 自定義事件的能力 (
$on, $emit, $dispatch, $broadcast
)
樣式、邏輯和介面的分離
前端開發經過這麼多年的發展,html、css和js的分開編寫應當是順理成章的,Vue.js沒有打破這個規則,通過 style 、 template 、 script 將樣式、檢視和資料邏輯進行了分離。詳見下面示例,來源於VUE.JS: A (RE)INTRODUCTION。
<!-- css -->
<style>
.message {
color: red;
}
</style>
<!-- template -->
<template>
<div class="message">{{ message }}</div>
</template>
<!-- js -->
<script>
export default {
props: ['message'],
created() {
console.log('MyComponent created!')
}
}
</script>
React
React可能是現在前端開發中最炙手可熱的UI框架了。在React的首頁最明顯的位置上展示者關於React的最核心的三個思想,它們分別是:
- Declarative(宣告式)
- Component-Based(元件化)
- Learn Once, Write AnyWhere(一學多寫)
宣告式
React和Vue.js的元件的使用都是宣告式的,宣告式的編寫方式會比命令式的編寫更加的直觀。關於宣告式和命令式的區別,可以參考Declarative programming和Imperative programming,這裡就不加詳述了。
元件化
誠然React和Vue.js在編寫大型程式的時候都是構建一顆元件樹,但React和Vue.js的元件卻有著不小的差異。先來看一個React元件的示例(來源React官網)。
var HelloMessage = React.createClass({
render: function() {
return <div style={divStyle}>Hello {this.props.name}</div>;
}
// style
var divStyle = {
color: 'white',
backgroundImage: 'url(' + imgUrl + ')',
WebkitTransition: 'all', // note the capital 'W' here
msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};
});
ReactDOM.render(<HelloMessage name="John" />, mountNode);
在React中,一切都是js,檢視、邏輯和樣式都是通過js來寫的。通過js來統一顛覆了html、css和js分離的原則,當然是褒貶不一了。在Vue.js中,分離帶來了清晰度,邏輯、檢視、樣式和資料可以分別處理,但在React中,一切都需要重新組織,甚至需要新的配套框架和設計模式,比如新的語言JSX就是用來簡化js帶來的麻煩的。但all in js讓很多事情變得簡單,js的快速發展也讓React脫離了css和html發展限制,可以實現更多的可能性,優化、擴充套件以及其他很多事情,就只要單純考慮js就可以了,而不必收到css和html的限制。
當然,這樣帶來的後果就是學習曲線的陡然增加,React甚至帶來了新的JSX語法,同時考慮到React全新的React思想,開發者想要開發生產環境的app,尤其是在將現有app用React重寫的時候,成本是要比Vue.js高出不止一個數量級的。
元件間資料傳遞
React推崇的是單向資料流動,也就是說,資料最好是從元件樹的頂端往葉子節點流動,儘量少的出現反向流動的情況。
用另外一種方式來說,React希望實現的immutable data,資料的不變性。只讀的資料能給我們帶來非常多的好處,併發、簡化邏輯、資料統一管理等等。
React提供了props和state兩種資料型別,props是實現資料從父元件往子元件傳遞的機制,而state則是提供了一種機制來實現元件的自更新,facebook是建議儘量少用該特性,因為其違反了immutable data和單向資料流動的設定。
因為React的資料設定讓其資料管理成為一個問題,業界出現了一些解決方案,其中最為著名的應該就是redux/flux了,有興趣的同學可以上github搜搜,都是開源的。
一學多寫
React背後是強大的facebook在開發維護,其目的不是要簡單的建立一種新的js的UI框架,相反,其想要讓React成為平臺無感知的UI開發思想。什麼意思呢?就是本節要說的learn once,write anywhere。facebook認為每個平臺不可能完全一樣,Web、Android、iOS、Windows Phone甚至Xbox,以及未來會出現的各種平臺,他們都會有自己的發展理念和發展路勁,不可能做到完全一樣,但不管平臺如何變化,基於平臺之上,建立Virtual DOM,React通過控制Virtual
DOM來實現介面變化。
也就是說Virtual DOM相當於是一箇中間層,隔離平臺的差異,從而實現統一的開發方式。
不敢說這樣的想法一定能成功,但就現在的發展勢頭來看,機會還是非常大的。尤其對於開發者來說極具吸引力,如果這一想法成為現實,以後React就可能像DOM一樣成為業界統一的標準。那對於iOS開發者來說,在Android上面開發會跟在iOS上開發一樣,不需要學習全新的Java語言,Android系統,更不要說各種Java特有的艱深複雜的工具了。
Native
個人感覺weex和react-native最大的不同是在Vue.js和React層面。這一點在react-native的命名上就非常容易看出來。在react-native剛出來的時候,其和React的關係是react-native依賴React。
"dependencies": {
"react": "~14.0.0"
}
而現在react-native和react則是同級別的。
"peerDependencies": {
"react": "~15.1.0"
}
react-native中最重要的檔名字也是Library,主要提供了一系列Native的能力。
檢視weex的原始碼,native部分的作用幾乎是一樣的,主要就是提供了一些列Native的元件,以及其他的一些能力。
這也就是為什麼本文將兩者的Native合為一談的原因,他們的本質是差不多的。
- 提供了js和native互動的橋樑Bridge
- 提供了一系列元件
- 提供了flexbox佈局支援
- 提供了事件支援
- ……
當然,因為weex和react-native的設計思想的差異,在native部分也存在差異,但我覺得這是因為js需要導致的,僅就native而言,兩者並沒有特別大的不一樣。
也許在不遠的將來,native部分會出來一個比較核心的框架,抽象出在構建App時js和native互動所需要的基本能力,同時提供擴充套件方式,讓各種類似react-native\weex這樣的框架可以專注於js層的設計。也許react-native就走在這條路上,誰知道呢?
展望
動態化的世界越來越精彩,對於weex和react-native的瞭解才剛剛入門,需要更多實操經驗來深刻體會到兩者的博大精深。weex和react-native各有千秋,開源的魅力也正是在此。