React native出來也快一週了,我寫了幾個demo,簡單看了看objc代碼並和開源前的咱們的一些結論(見後文)交叉驗證。簡單地從前端工程師和系統總體角度說一下React native的特色和優劣吧。css
react native充分利用了Facebook的現有輪子,是一個很優秀的集成做品,而且我相信這個團隊對前端的瞭解很深入,不然不可能讓Native code「退居二線」。html
對應到前端開發,整個系統結構是這樣:前端
- JSX vs HTML
- CSS-layout vs css
- ECMAScript 6 vs ECMAScript 5
- React native View vs DOM
- 無需編譯,我在第一次編譯了ipa裝好之後,就再也沒更新過app,只要更新雲端的js代碼,reload一下,整個界面就全變了。
- 多數佈局代碼都是JSX,全部Native組件都是標籤化的XML,這對於前端程序員來講,下降了很多學習成本,也大大減小了代碼量,不信你能夠看看JSX編譯後的代碼。
- 複用React系統,也減小了必定學習和開發成本,更重要的是利用了React裏面的分層和diff機制。js層傳給Native層的是一個diff後的json,而後由Native將這個數據映射成真正的佈局視圖。
- css-layout也是點睛之筆,前端能夠繼續用熟悉的類css方式來編寫佈局,經過這個工具轉換成constrain佈局。
- 系統只有js-objc的單向調用,就是把原生UI組件的方法經過javascritcore或者webview(低版本iOS)映射到js中來,整個調用過程是異步的,這樣的設計令React native可讓js運行在桌面chrome中,經過websocket鏈接Native code和桌面chrome,極大地方便了調試。對其中的機制Bang的一篇文章寫得很詳細,我就不拾人牙慧了:http://blog.cnbang.net/tech/2698/ 。但這樣設計也會帶來一些問題,後面說。
- 點按操做也被抽象成了一組組件(TouchableXXX),這種抽象方式是我在以前作相似工做中沒有想到的。facebook還列出Native爲何和web「手感」不一樣的緣由:實時的點按反饋和取消能力。http://facebook.github.io/react-native/docs/gesture-responder-system.html#content 這套相應機制設計得很完善,能像Native code那樣控制整個點按操做的全部過程。
- Debug至關方便!修改了js之後,經過內建的nodejs watcher編譯成bundle,在模擬器裏面按cmd+r就能夠看到效果。並且按cmd+d,能夠打開一個chrome窗口,全部的js都移到了chrome裏面運行,因此什麼斷點單步打調用棧,都不在話下。
上面的既是特色也是優勢,下面說說缺點,或者應該說:「仍然遺留的問題」,在我看來,這個方案已經超越了Hybird方案。java
- 系統仍然(不得不)依賴原生組件暴露出來的組件和方法。舉兩個例子,ScrollView這個組件,在Native層是有大量事件的,scrollViewWillBeginDragging, scrollViewWillEndDragging,scrollViewDidEndDragging等等,這些事件在現有的版本都沒有暴露,基本上作不了組件聯動效果。另外,這個版本中有大量組件是iOS only的:ActivityIndicatorIOS、DatePickerIOS、NavigatorIOS、PickerIOS、SliderIOS、SwitchIOS、TabBarIOS、AlertIOS、AppStateIOS、LinkingIOS、PushNotificationIOS、StatusBarIOS、VibrationIOS,反過來看,剩餘的都是一些抽象程度極強的基本組件。這樣,用戶必須在不一樣的平臺下寫兩套代碼,並且全部能力仍然強烈依賴 React native 開發人員暴露的接口。
- 因爲最外層是React,初次學習成本高,不像往常的Hybird方案,只要多學幾個JS API就能夠開始幹活了。固然,React的確讓後續開發變得簡單了一些,這麼一套外來的(基於iOS)、殘缺不全的(css-layout)在React的包裝下,的確顯得不那麼面目可憎了。
另外,React Native仍然很不完善。文檔還不全,我基本上是看着他的示例代碼完成的demo,集成到已有app的文檔也是今天才出來。按照官方的說法,Android版本要到半年後才發佈: http://facebook.github.io/react/blog/#when-is-react-native-android-coming ,屆時整個系統設計可能還會有很大的變化。node
PS,在使用Tabbar的時候,我驚喜的發現他們竟然用了iconfont方案,我如今手頭的項目中也有一樣的實現,不過API怎麼設計一直很頭疼。結果,我發現他是這麼寫的:react
<TabBarItemIOS name="blueTab" icon={_ix_DEPRECATED('favorites')} ....>
在 _ix_DEPRECATED
的定義處,有一句註釋: // TODO(nicklockwood): How can this fit our require system?
android
HOW?git
以上。程序員
下面是一週前,在React native還沒開源的時候,經過反解ipa的一些分析過程,有興趣的能夠看看。github
背景和調研手段
React Native還沒開源,最近和組裏兄弟反編譯了Facebook Group(這個應用是用React Native實現的)的ipa代碼,出來幾百個JS文件,格式化一下,花了幾天時間讀了一下源碼,對React Native的內部核心機制算是有了一個基本瞭解。
React Native的核心實現:
先簡單說幾點,詳細的等回頭更新。
- React Native裏面沒有webview,這貨**不是Hybrid app**。
- 再說React Native的核心,iOS Native code提供了十來個最核心的類(RCTDeviceEventEmitter、RCTRenderingPerf等)、或組件(RCTView、RCTTextField、RCTTextView、RCTModalFullscreenView等),而後由React Native的JS部分,組成二十來個基本組件(Popover、Listview等),交由上層的業務方來使用(THGroupView)。
- 就如他們在宣傳時所說,他們實現了一套相似css的子集,用來解決樣式問題,至關複雜和強大,靠這個才能將Native的核心組件組成JS層的基本組件再組成業務端的業務組件,我的猜想是採用CSSLayout的C語言版本實現的。
- 在React Native中,寫JS的工程師解決的是「將基本組件拼裝成可用的React組件」的問題,寫Native Code的工程師解決的是「提供核心組件,提供足夠的擴展性、靈活性和性能」的問題。
React Native的設計考慮:
ReactJS對React Native有着直接的影響(我沒真正在生產環境中用過React,只用過Angular,下面的觀點可能有誤差)
ReactJS是這麼設計的:
1. ReactJS 經過createElement返回的不是某個實體DOM對象,而只是一個數組
2. 經過源碼中 ui/browser/ 目錄中的代碼,將這個數組轉換成DOM
另外,Facebook本身有JSX,CSSLayout等開源項目(本身去github上找介紹吧)
有了React再考慮React Native,很天然就想到了一套最有效率的搞法:
1. 將 ui/browser 裏面的代碼替換成一套 Native 的橋接JS(實際上,iOS版是經過
injectGenericComponentClass方法,將核心組件的方法注入到JS裏面 ),不就用上React的MVVM,自動將數據映射到Native了麼
2. Native code裏面實現三組核心API,一組提供核心組件的API(create、update、delete),一組事件方法(ReactJS裏面的EventEmitter ),一組對Style進行解析(貌似是用的CSSLayout的C語言版本)以及返回Style的ComputedStyle(React Native裏面叫meatureStyle)
這樣,用上了ReactJS自己的全部核心功能和設計思路,Native的開發也足夠簡單。
React Native的優點和劣勢:(非最終結論,可能會更新):
React Native的優點:
相對Hybird app或者Webapp:
- 不用Webview,完全擺脫了Webview讓人不爽的交互和性能問題
- 有較強的擴展性,這是由於Native端提供的是基本控件,JS能夠自由組合使用
- 能夠直接使用Native原生的「牛逼」動畫(在FB Group這個app裏面,面板滑出帶一點果凍彈動,面板基於某個點展開這種動畫隨處可見,這種動畫用Native code來作小菜一碟,可是用Web來作就難上加難)。
相對於Native app:
- 能夠經過更新遠端JS,直接更新app,不過這快成爲各家大型Native app的標配了…
劣勢:
- 擴展性仍然遠遠不如web,也遠遠不如直接寫Native code(這個不用廢話解釋了吧)
- 從Native到Web,要作不少概念轉換,勢必形成雙方都要妥協。最終web要用一套CSS的閹割版,Native要費勁地把這個閹割版轉換成native原生的表達方式(好比iOS的Constraint\origin\Center等屬性),兩邊都會不爽。
參考:https://www.zhihu.com/question/27852694