1. 程式人生 > >【前端前沿看點】深度本質分析對比weex和react native

【前端前沿看點】深度本質分析對比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 programmingImperative 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各有千秋,開源的魅力也正是在此。