轉載自:http://www.jianshu.com/p/b88944250b25javascript
React Native 誕生於 2015 年,名副其實的富二代,主要使命是爲父出征,與 Apple 和 Google 抗衡,爲開發者帶去一套跨平臺、動態更新的 Javascript 框架,口號是:Learn once, write anywhere:Build mobile apps with React。在試圖推翻 Android 和 iOS 壓制的同時,還提攜了一把自家兄弟:React。html
從誕生之日 React Native 就充滿了期待和爭議。期待是無數開發者但願不用忍受頻繁發版的噩夢,也不用同時爲兩個平臺開發業務邏輯幾無差異的兩個 App;爭議是 React Native 真的能以一己之力救大衆於水火嗎?React Native 在跨平臺時還能保持良好的用戶體驗嗎?前端
固然咱們知道,這種問題向來都是仁者見仁,智者見智。比起一味的疑惑、爭論,還不如來好好看看這貨到底是個啥?甚至本身動手來玩一把。java
本文主要針對兩類讀者:node
下面咱們來看下 Hybrid 及 React Native 等開發模式包含了哪些常規移動開發所不具有的優點。react
傳統的客戶端開發模式是怎樣的呢?android
Android 與 iOS Team 分別編寫客戶端代碼,打包,分發到 Play Store 和 Apple Store,經過更新 JSON 數據來更新頁面。ios
不過,當客戶端發生嚴重問題而服務器上沒法 quick fix 時,就不得不從新發版。git
對國外 Android 市場而言還好,由於能經過 Play Store 快速更新;國內 Android 市場則因爲分發渠道太雜,很難及時把新版本當即推送給全部用戶,固然這也是爲什麼熱修復技術在國內盛行而國外冷清的緣由;而 Apple Store 則須要必定的審覈時間,並且最近又在抓 iOS 熱修復框架如 JsPatch、Rollout 等。程序員
相比而言,Hybrid 和 RN/Weex 模式除了能下發 Json 數據來刷新界面內容,更能直接下發業務邏輯代碼,直接實現總體 App 的更新。並且,它們不用在意 Android 和 iOS 兩個平臺,由於一份 JS 代碼寫好後,把 JS Bundle 放在服務器上,全部的客戶端當即更新。
通常而言,同一款產品的 Android 和 iOS 兩端除 UI 有些許不一樣外,多數業務邏輯幾乎徹底一致,這便形成了人力的浪費。
而最近 Instagram 的官博 React Native at Instagram 一文中已經提到,利用 RN (React Native 縮寫,下同) 開發的 feature 能夠實現 85% - 99%
的代碼複用率。這意味着咱們能夠用更少的人力成原本達到相同的效果。
實現上面的效果有兩種開發框架:混合開發框架 Cordova 和基於 Javascript 的 React-Native、Weex 框架。
下面我從本身的實踐經驗出發作些比較,也歡迎讀者提出本身見解。
最開始以爲 RN 的學習成本比較大,因此首先考慮了 Weex 框架,聽說是阿里巴巴良心出品。不過在嘗試後不得不選擇了放棄,緣由有這幾點:
最基本
的 ListView,在 iOS 運行良好,而一樣的 Demo 代碼到了 Android 這邊的下拉刷新
就出現了問題,這使得咱們開始警戒;固然,我是很但願國內也能推出優質的開源項目來和國外大廠抗衡的,不過真正優質的大型開源項目每每除了開發者的我的能力,和公司的戰略和制度關係也很大。
這裏的 Hybrid 開發主要針對 Cordova 框架,其實在放棄 Weex 以後咱們仍是沒考慮 RN,而是轉過去了解 Cordova,不過作了大體瞭解後也放棄了。主要硬傷有兩點:
性能和用戶體驗是移動 App 的命根子。
所以,綜合考慮下來,咱們仍是決定相信 Facebook 並採用 RN。
上面我提到了 RN 的一些優點,不過做爲開發者更加須要明確其劣勢,我總結了下大概有如下幾點劣勢:
split apk
的技術就能縮小到到 1MB 左右的增幅。對於一個用 RN 搭建的移動 App,在啓動後會從服務器下載最新的 JS Bundle 文件,而後由本地 JavascriptCore 引擎對 JS 文件進行解析,並利用 Bridge 映射到對應的 Native 方法和 UI 控件。獲得的效果是:
首先 IDE 方面,RN 推薦了一些工具:
本人的話目前採用的是 Sublime
,由於我的經常使用 Sublime,並且第三方插件很豐富,輕量方便。下面簡單說下配置,感興趣的小夥伴能夠看下。
固然,用 Atom 的小夥伴天然要首先考慮 Nuclide。
引入 RN 有兩種方法:從零構建;集成到已有項目。
先說第一種,從零開始構建,比較簡單,遵循官方文檔 Getting Started 基於你本身的操做系統和平臺一步步安裝相關的依賴,而後利用以下命令:
react-native init AwesomeProject
你就建立好一個 RN 工程項目了,結構以下:
裏面有四個文件夾:
android
/ ios
:各自存放了一個相關平臺的工程 project,能夠直接下拉 JS Bundle 並運行,對於移動端小白而言能夠不用管裏面的具體實現;node_modules
:裏面是自動生成的 node
依賴之類的文件,經過讀取 package.json
裏的配置來生成;js
:這個文件夾最爲重要,咱們的開發都在這個文件夾裏,把寫好的 js
文件打包下發給 client 就會自動生效。有不少公司是但願在現有 App 的基礎上集成 RN
來開發一些特定的 Feature,這種狀況就不能參考上面的方法了。在 RN 的官方文檔裏有一節 Integration with Existing Apps , 只須要按照一步步作便可。
以 Android 爲例,大概要作如下幾步:
gradle
依賴:compile "com.facebook.react:react-native:+" // From node_modules.
;Activity
,指定 JS bundle
和入口 Component
名字即會自動在這個 Activity
裏去加載 JS bundle
文件;總之須要說明的是,即便是移動端小白,也能夠遵循文檔裏的指示完成這一步。接下來的大部分時間只要關心 JS 端開發就好了。
咱們知道 RN 採用了 React 和 ES6 的語法,因此咱們必須先對這些語法有必定了解才能去讀 RN 的代碼。
關於 Javascript
,我推薦 W3School 裏的 JS語法 和 MDN 裏的 JS手冊,你們只要對一些基礎語法作些瞭解就能夠。
關於 React
,我推薦 阮一峯 寫的 React 入門實例教程,基本上把文章讀一遍,再本身動手寫一遍,就能理會到 React 的大體用法了。
關於 ES6
、ES7
、JSX
等,感興趣的能夠看一下 RN 文檔中 Javascript Environment 裏提到的支持的方法,須要時再來查詢也能夠。也能夠看 Babel
出的 Learn ES2015 手冊。
這裏有一個很不錯的 GitHub 項目,幫助你經過交互性的例子來快速上手語法知識:React Native Express。
簡單熟悉了 React
語法後,基本能正常閱讀 RN 的示例代碼了。
正式開發 App 的第一步固然就是寫 UI 界面了,因爲 RN 已經封裝好了一套 JS 的 UI 組件,這些組件會自動在 Android/iOS 端調用對應的原生 UI 組件,所以咱們只須要熟悉這些 UI 組件的用法及屬性、回調方法便可。
咱們能夠在文檔的 Components 看到很多組件,好比View, Text, Button, Image, Switch
, 還有咱們用的最多的 ScrollView
和 ListView
。
在讀文檔時,咱們能夠先經過一邊寫代碼一邊讀文檔的方式進行,RN 很是貼心,直接在 Web 裏嵌入了模擬器,咱們只要修改編輯框裏的代碼,當即就能在右邊的模擬器看到效果。這極大的下降了咱們的學習成本。
另外,在學習一個組件時,咱們要區分哪一個屬性是某個平臺特有的。好比下面兩個 Text 的屬性:textBreakStrategy
只會在 Android 上生效,而 adjustsFontSizeToFit
只能夠用在 iOS 上。
而後,若是你但願在 Android 和 iOS 裏顯示不一樣的內容怎麼辦呢?RN 裏有一節是Platform Specific Code,能夠有以下幾種形式來進行區分:
if (Platform.OS === 'ios') { // stuff for ios } else { // stuff for android }
除此以外,UI 組件的用法學習就很相似常規的 Html 標籤了,只要知道其使用方式便可,甚至須要用的時候再來查文檔也行。
學完上面的咱們已經可以寫出 UI 界面了,並且這套界面已經可以在不一樣平臺上轉化成各自平臺的 Native UI 了。而後,咱們就須要去網絡層請求真實數據了。
RN 裏提供了 Fetch API 來進行實現。舉個例子,你想要經過 GET 方法去請求數據並轉化成 JSON,能夠經過以下代碼實現:
fetch('https://facebook.github.io/react-native/movies.json') .then((response) => response.json()) .then((responseJson) => { return responseJson.movies; }) .catch((error) => { console.error(error); });
熟悉 Reactive 編程的夥伴應該對這樣的語法不陌生,好比 Android 上的 RxJava; iOS 上的 RxSwift;Web 上的 RxJS。上面 function 的功能就是:請求網址 https://facebook.github.io/react-native/movies.json
,把返回的 Response 轉化成 JSON object,取出 JSON object 裏的 movies
字段。同時,若是發生 error 會被 catch 住。
固然,上面是最基本的 GET 請求,Fetch API 還支持自定義 Headers,更換 Method,添加 Body 等。
fetch('https://mywebsite.com/endpoint/', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ firstParam: 'yourValue', secondParam: 'yourOtherValue', }) })
上面構建了一個基本的 POST 請求,添加了本身的 Headers:Accept
和Content-Type
,添加了 Body。
所以看下來,RN 裏的網絡請求不只具有了 Reactive 編程的簡潔,也能自定義常規的 Http 請求,寫法簡單。
除了 Fetch API 以外,RN 還內置了 XMLHttpRequest API(俗稱 AJAX),並且支持TCP 全雙工通訊方式 WebSocket。
調試是不少程序員很是關注的一個環節,由於 RN 是用 JS 寫完後到 Native 解釋成 Native 方法來執行的,所以若是能快速調試 JS 代碼是很是重要的一環。
最開始 RN 的調試功能比較弱,不過如今的 Debugging 功能在我看來仍是很不錯的。通常來說能夠有如下幾個調試方式:
RN 裏默認集成了 In-App 的錯誤提示方式,即在 App 運行過程當中會彈出全屏的報錯信息呈現給你,而你也能夠經過閱讀具體的錯誤信息快速找到錯誤緣由。經過點擊這個錯誤信息裏的某一行,會當即自動打開對應的代碼。
在開發 Client 時,咱們通常都會用 Log.log()
來打印一些運行時變量的值,而後實時查看打印出來的 log 來調試,在 RN 也同樣,你只要在 JS 裏寫一句 console.log('this is log data')
,就會自動在 Client 的常規 log 裏能看到,好比 Android 的 adb logcat
裏就會自動打印出'this is log data'
一行。
這個殺器的最牛逼之處就是能夠像 Client 同樣,逐行調試代碼!
咱們來看下面一張圖。從左往右。先是文件目錄,咱們選中了 index.js
文件夾,而後第二個 Tab,是 index.js
的內容。這裏關鍵的是我能夠直接選中某一行代碼設斷點。當 Client 運行到這一行時,就會在第三個 Tab 裏打印出運行時環境及變量。咱們能夠看到 props
裏就有咱們傳進去的變量值。
有了以上幾種調試方式,咱們幾乎能夠和常規的 Native 開發同樣來調試 RN 代碼了,不得不說 RN Team 確實牛 x 啊!
這又是另外一個牛 x 之處啊。
不少人以爲 RN 限制太多,只能支持有限的 View 組件和有限的方法,難以發揮 Client 的最大性能。簡單點說,在 Client 能夠繪製複雜的 View,能夠調用高性能 C++ 等底層代碼,但 RN 卻作不到。
因而,RN 裏提出了 Native Modules
和 Native UI Component
兩種技術。
所謂 Native Modules,就是本身在 Client 寫好了某些方法,因爲某些緣由這些方法不太方便或者沒法搬到 RN 裏面,那麼,咱們能夠在 Client 把這些方法暴露出來給 RN,而後在 JS 裏能夠像 import 普通的 module 同樣把這些 Native Modules 引入進去,直接調用。
具體的實現方法能夠參考文檔 iOS Native Modules 和 Android Native Modules。
不少時候咱們在寫 Client 時,爲了實現 Designer 天馬行空的設計,經常須要自定義 View,即本身繪製某些系統並不提供的特定 UI。可想而知,這些 View 確定不會出如今 RN 的 UI Component 裏。
那麼,咱們就須要首先在 Native 層本身寫好一個自定義 View,而後利用Native UI Component
技術把這個 View 及其中某些 public 方法暴露給 RN,那麼 RN 就能直接 import 進來並顯示了。
具體的實現方法能夠參考文檔 iOS Native UI Component 和 Android Native UI Component。
若是讀過文檔不是很理解的小夥伴能夠留言,我再 post 一些 demo 代碼上來
這裏借鑑下前段時間舊金山的 React Native 會議上的一些優劣總結給讀者以參考。固然不必定對,僅供參考。
RN 的優勢:
RN 的缺點:
適合下面這些人/公司:
下面這些人要稍微考慮下:
幾個月前我對 React Native 也很是不看好,固然如今也沒有說很是看好。或者說,寫這篇文章毫無爲 React Native 佈道之意。
接觸 React Native 主要是由於業務須要,PM 但願可以隨時改動某塊變化較大的模塊,常規的開發提交流程每每須要較長的時間,而熱修復技術自己並未獲得 Google 和 Apple 的官方承認,也就是隨時可能因破壞生態安全之名被取締。
所以才考慮去了解 Hybrid 開發和 JS Native 開發模式,在瞭解過程當中,又因爲性能差、用戶體驗很差而放棄 Hybrid,因爲社區不完善、Bug 較多等緣由放棄 Weex,最終才選擇了 React Native,開始學習 React、JSX等語法。
目前使用下來對 React Native 的一些我的感覺:
6MB
左右的 size 增幅,不過在採用了 split apk
後就只有 1MB
左右增幅。關於React Native一直以來都有不少爭議。
不過我想說的是,React Native 所表明的跨平臺、動態更新技術已經引發了全世界開發者關注,並且這種技術勢必會是將來的需求和潮流。React Native 不必定會成功,但至少目前 React Native 已是這一領域的領跑者。
而寫這篇文章的目的,就是但願告訴更多開發者,React Native 並不完美,但值得一試。
謝謝。