React Native入門指南

轉載自: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

  • 想要入門 RN 的人,在閱讀官方文檔前先對 RN 造成一個總體的印象
  • 對 RN 心存好奇,在猶豫是否要入坑的開發者,能夠經過本文對 RN 更客觀全面的認識

目錄

  • React Native 好在哪
    • 跨平臺+動態更新
    • 代碼複用
    • RN vs Weex
    • RN vs Hybrid
    • RN 劣勢
  • React Native 運行機制
  • RN 開發環境搭建
  • 引入 React Native
    • Build from Scratch
    • 集成到已有項目
  • Javascript、React 及 ES六、JSX 語法
  • UI 層
  • 網絡請求層
  • Debugging 調試
    • In-App 報錯
    • Console.log
    • 大殺器:Chrome 逐行調試
  • 從 JS 調用 Native 方法或顯示自定義 Native View
    • Native Modules:JS 裏直接調用 Native(Java/Swift) 方法
    • Native UI Component:JS 裏直接調用自定義的 Native View
  • React Native 適合你嗎?
  • 爲何要寫這篇文章

1、React Native 好在哪

下面咱們來看下 Hybrid 及 React Native 等開發模式包含了哪些常規移動開發所不具有的優點。react

1. 跨平臺+動態更新

傳統的客戶端開發模式是怎樣的呢?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 放在服務器上,全部的客戶端當即更新。

2. 代碼複用

通常而言,同一款產品的 Android 和 iOS 兩端除 UI 有些許不一樣外,多數業務邏輯幾乎徹底一致,這便形成了人力的浪費。

而最近 Instagram 的官博 React Native at Instagram 一文中已經提到,利用 RN (React Native 縮寫,下同) 開發的 feature 能夠實現 85% - 99% 的代碼複用率。這意味着咱們能夠用更少的人力成原本達到相同的效果。

3. RN vs Weex

實現上面的效果有兩種開發框架:混合開發框架 Cordova 和基於 Javascript 的 React-Native、Weex 框架。

下面我從本身的實踐經驗出發作些比較,也歡迎讀者提出本身見解。

最開始以爲 RN 的學習成本比較大,因此首先考慮了 Weex 框架,聽說是阿里巴巴良心出品。不過在嘗試後不得不選擇了放棄,緣由有這幾點:

  • Bug 較多。咱們最早測試了最基本的 ListView,在 iOS 運行良好,而一樣的 Demo 代碼到了 Android 這邊的下拉刷新就出現了問題,這使得咱們開始警戒;
  • 社區、文檔弱,GitHub Issue 基本是中文。固然我毫無歧視中文之意。我認爲,一套項目開源是真正意義是但願藉助開源社區的力量,一塊兒來完善改進,所以要優先推崇英文,使項目國際化,獲得全世界開發者的共同支持,這樣纔是可持續的模式。而 Weex 的 Issue 裏放眼望去基本 90% 都是中文,不管提問者仍是項目維護者。這一點直接把國外優秀的開發者拒之門外,也很難讓我看到多麼長遠的將來。
    下面是摘取的 RN 裏的一則中文 issue:

Issue is for bug report, not for Q&A
  • Contributor 差異。由於上面一點,Weex 的 Contributor 只有 91 我的,而 React-Native 的 Contributor 有 1214 人。Contributor 是用來幹嗎的?除了支持新功能,還有就是修復 bug 啊。Weex/RN 都是但願一統 Android + iOS 的,這麼偉大的目標,這麼艱鉅的工程,不是幾我的能夠輕輕鬆鬆搞定的。
  • 公司背景(來自YY)。你們都知道 RN 來自 Facebook,Weex 來自阿里巴巴。若是想一窺它們的將來,須要先想一下這種技術對他們各自的意義。你們都清楚,Facebook、Google、Apple 是當今當之無愧的巨頭,在移動互聯網這波浪潮裏,Google 掌握了 Android 法器,Apple 控制了 iOS 神器,Facebook 呢?並無這些系統級入口。固然 Windows 的經歷也讓 Facebook 並不那麼傾向去開發一個新的移動操做系統來競爭。那怎麼辦?React Native 應運而生,打出的口號就是: Learn once, write anywhere。什麼意思,沒錯,就是明確告訴你學一次就能夠同時開發兩個平臺了。這一點可一直都是移動端開發人員和創業公司的理想。有人說了,Apple 這麼強勢,RN 要是太囂張,分分鐘把你禁掉。這時咱們就要來看看 RN 的Showcase 了,哪些 App 應用了 RN 呢?Facebook, Instagram, Airbnb, Walmart, QQ, 京東等,這回 Apple 要禁 RN 就要稍微掂量下這些大廠的意見吧。

固然,我是很但願國內也能推出優質的開源項目來和國外大廠抗衡的,不過真正優質的大型開源項目每每除了開發者的我的能力,和公司的戰略和制度關係也很大。

4. RN vs Hybrid

這裏的 Hybrid 開發主要針對 Cordova 框架,其實在放棄 Weex 以後咱們仍是沒考慮 RN,而是轉過去了解 Cordova,不過作了大體瞭解後也放棄了。主要硬傷有兩點:

  • 性能短板。你們知道 Hybrid 是基於 WebView 的,在 Android 上的性能缺陷很是明顯;而 RN 是利用 JSCore 轉化成 Native 運行的,性能相對而言好很多;
  • 用戶體驗。瞭解移動產品的人都知道用戶體驗的重要性,RN 的體驗和原生的幾乎沒有差異,而 Webview 的實現是網頁開發思路,體驗會相差很大。

性能和用戶體驗是移動 App 的命根子。

所以,綜合考慮下來,咱們仍是決定相信 Facebook 並採用 RN。

5. RN 劣勢

上面我提到了 RN 的一些優點,不過做爲開發者更加須要明確其劣勢,我總結了下大概有如下幾點劣勢:

  • 學習成本。Weex 的寫法就是相似常規的 Html/JS,對於前端人員來講很容易上手,就算了非前端人員來講也花不了多久。而 RN 是在 React.js 上進行改進造成的一套語法,和常規前端差異較大,所以須要好幾天的學習適應。固然我以爲優秀的程序員的基本素質之一就是能快速學習、練習並熟練一種新語言的。我我的的話大概花了兩三天的時間已經能完成一套涵蓋網絡、JS與Native通訊的頁面了,對於 React.js 語法也上手很快。
  • 安裝包 Size。對於 iOS 而言影響不算很大,對於 Android 來講,我嘗試後發現引入 RN 會給 apk 帶來 6MB 左右的增幅,不過利用 split apk 的技術就能縮小到到 1MB 左右的增幅。
  • 首次加載耗時。你們知道 RN 須要從服務器下載 JS bundle,而後在本地轉化成 Native code 運行的,因此在第一次打開 App 時須要花費一些時間進行下載和刷新。固然咱們能夠在發佈 client 時內置一個寫好的 js 文件在本地做緩存用。

2、React Native 運行機制

對於一個用 RN 搭建的移動 App,在啓動後會從服務器下載最新的 JS Bundle 文件,而後由本地 JavascriptCore 引擎對 JS 文件進行解析,並利用 Bridge 映射到對應的 Native 方法和 UI 控件。獲得的效果是:

  1. 一樣的 RN 代碼,下發到 Android 和 iOS 不一樣平臺中,會自動調用對應 Native 的 UI 控件,保證了各平臺用戶體驗的連貫性;
  2. 開發者就算是移動端小白,只要有 Web 基礎,經過編寫一套 RN 端代碼就能夠同時完成 Android 與 iOS App 的開發;
  3. 因爲能夠利用 JS bundle 同時下發數據和業務邏輯,這意味着你能夠像 Web 開發同樣,實時迭代更新你的移動端 App,無需在瞭解各自平臺的熱修復技術;
  4. Native Modules,這是 RN 強大的一個擴展性,容許你經過簡單的代碼就能實如今 JS 裏直接調用你本身的 Native 方法;
  5. Native Components,若是你本身實現了一些複雜的 Native UI 組件,而這些組件還沒有被 RN 支持,你能夠利用 Native Components 快速把原生組件引入到 RN 中並能夠直接在 JS 裏更新這些組件的狀態。

3、RN 開發環境搭建

首先 IDE 方面,RN 推薦了一些工具:

  • Nuclide 是 Facebook 內部用來開發 RN 的工具,Debug 功能強大。只不過這是一款Atom 的插件,意味着你必須先安裝 Atom,再來安裝這款開發插件;
  • Deco 是專爲開發 RN 誕生的工具,能夠快速搜索開源的第三方 RN 組件並直接插入到代碼中,用 MacOS 的同窗能夠嘗試下。我本人最開始也是試用這個,上手簡單、小巧簡潔。不足的是功能有點簡單,不管是 Debug 功能仍是代碼檢查之類的都不具有;
  • Sublime 能夠經過第三方包來達到不錯的開發效率,各方面還算可圈可點;
  • Visual Studio 這款也是蠻強大的 IDE,以前有用過的小夥伴能夠試一下。

本人的話目前採用的是 Sublime,由於我的經常使用 Sublime,並且第三方插件很豐富,輕量方便。下面簡單說下配置,感興趣的小夥伴能夠看下。

  1. Babel 用來高亮 React JSX 語法,支持 ES6,而 React-Native 就是搭建在 React.js基礎上的;
  2. React-Native-Snippets 能夠快速生成 RN 的一些模版代碼;
  3. ESLint 超級強大的 Lint 工具,支持 ES六、JSX 語法檢查,並且還有 React 和 RN 的插件,比純粹的 JSXHint/JSLint 都強大;

固然,用 Atom 的小夥伴天然要首先考慮 Nuclide

4、引入 React Native

引入 RN 有兩種方法:從零構建;集成到已有項目。

1. Build from Scratch

先說第一種,從零開始構建,比較簡單,遵循官方文檔 Getting Started 基於你本身的操做系統和平臺一步步安裝相關的依賴,而後利用以下命令:

react-native init AwesomeProject

你就建立好一個 RN 工程項目了,結構以下:


RN 目錄結構

裏面有四個文件夾:

  • android / ios:各自存放了一個相關平臺的工程 project,能夠直接下拉 JS Bundle 並運行,對於移動端小白而言能夠不用管裏面的具體實現;
  • node_modules:裏面是自動生成的 node 依賴之類的文件,經過讀取 package.json 裏的配置來生成;
  • js:這個文件夾最爲重要,咱們的開發都在這個文件夾裏,把寫好的 js 文件打包下發給 client 就會自動生效。
2. 集成到已有項目

有不少公司是但願在現有 App 的基礎上集成 RN 來開發一些特定的 Feature,這種狀況就不能參考上面的方法了。在 RN 的官方文檔裏有一節 Integration with Existing Apps , 只須要按照一步步作便可。

以 Android 爲例,大概要作如下幾步:

  1. 添加 gradle 依賴:compile "com.facebook.react:react-native:+" // From node_modules.
  2. 建立空的 Activity ,指定 JS bundle 和入口 Component 名字即會自動在這個 Activity裏去加載 JS bundle 文件;
  3. 在 Activity 裏監聽 onBackPressed 事件,用來與 JS 端協做處理返回鍵點擊事件。
  4. 啓動 server,運行 App 便可。

總之須要說明的是,即便是移動端小白,也能夠遵循文檔裏的指示完成這一步。接下來的大部分時間只要關心 JS 端開發就好了。

5、Javascript、React 及 ES六、JSX 語法

咱們知道 RN 採用了 React 和 ES6 的語法,因此咱們必須先對這些語法有必定了解才能去讀 RN 的代碼。

關於 Javascript,我推薦 W3School 裏的 JS語法 和 MDN 裏的 JS手冊,你們只要對一些基礎語法作些瞭解就能夠。

關於 React,我推薦 阮一峯 寫的 React 入門實例教程,基本上把文章讀一遍,再本身動手寫一遍,就能理會到 React 的大體用法了。

關於 ES6ES7JSX等,感興趣的能夠看一下 RN 文檔中 Javascript Environment 裏提到的支持的方法,須要時再來查詢也能夠。也能夠看 Babel 出的 Learn ES2015 手冊

這裏有一個很不錯的 GitHub 項目,幫助你經過交互性的例子來快速上手語法知識:React Native Express

6、UI 層

簡單熟悉了 React 語法後,基本能正常閱讀 RN 的示例代碼了。

正式開發 App 的第一步固然就是寫 UI 界面了,因爲 RN 已經封裝好了一套 JS 的 UI 組件,這些組件會自動在 Android/iOS 端調用對應的原生 UI 組件,所以咱們只須要熟悉這些 UI 組件的用法及屬性、回調方法便可。

咱們能夠在文檔的 Components 看到很多組件,好比View, Text, Button, Image, Switch, 還有咱們用的最多的 ScrollView 和 ListView

在讀文檔時,咱們能夠先經過一邊寫代碼一邊讀文檔的方式進行,RN 很是貼心,直接在 Web 裏嵌入了模擬器,咱們只要修改編輯框裏的代碼,當即就能在右邊的模擬器看到效果。這極大的下降了咱們的學習成本。


Text Component

另外,在學習一個組件時,咱們要區分哪一個屬性是某個平臺特有的。好比下面兩個 Text 的屬性:textBreakStrategy 只會在 Android 上生效,而 adjustsFontSizeToFit 只能夠用在 iOS 上。


Platform Specific Properties

而後,若是你但願在 Android 和 iOS 裏顯示不一樣的內容怎麼辦呢?RN 裏有一節是Platform Specific Code,能夠有以下幾種形式來進行區分:

if (Platform.OS === 'ios') { // stuff for ios } else { // stuff for android }

除此以外,UI 組件的用法學習就很相似常規的 Html 標籤了,只要知道其使用方式便可,甚至須要用的時候再來查文檔也行。

7、網絡請求層

學完上面的咱們已經可以寫出 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:AcceptContent-Type,添加了 Body。

所以看下來,RN 裏的網絡請求不只具有了 Reactive 編程的簡潔,也能自定義常規的 Http 請求,寫法簡單。

除了 Fetch API 以外,RN 還內置了 XMLHttpRequest API(俗稱 AJAX),並且支持TCP 全雙工通訊方式 WebSocket

8、Debugging 調試

調試是不少程序員很是關注的一個環節,由於 RN 是用 JS 寫完後到 Native 解釋成 Native 方法來執行的,所以若是能快速調試 JS 代碼是很是重要的一環。

最開始 RN 的調試功能比較弱,不過如今的 Debugging 功能在我看來仍是很不錯的。通常來說能夠有如下幾個調試方式:

1. In-App 報錯

RN 裏默認集成了 In-App 的錯誤提示方式,即在 App 運行過程當中會彈出全屏的報錯信息呈現給你,而你也能夠經過閱讀具體的錯誤信息快速找到錯誤緣由。經過點擊這個錯誤信息裏的某一行,會當即自動打開對應的代碼。


In-App Error
2. Console.log

在開發 Client 時,咱們通常都會用 Log.log() 來打印一些運行時變量的值,而後實時查看打印出來的 log 來調試,在 RN 也同樣,你只要在 JS 裏寫一句 console.log('this is log data'),就會自動在 Client 的常規 log 裏能看到,好比 Android 的 adb logcat 裏就會自動打印出'this is log data'一行。

3. 大殺器:Chrome 逐行調試

這個殺器的最牛逼之處就是能夠像 Client 同樣,逐行調試代碼!

咱們來看下面一張圖。從左往右。先是文件目錄,咱們選中了 index.js 文件夾,而後第二個 Tab,是 index.js 的內容。這裏關鍵的是我能夠直接選中某一行代碼設斷點。當 Client 運行到這一行時,就會在第三個 Tab 裏打印出運行時環境及變量。咱們能夠看到 props 裏就有咱們傳進去的變量值。


Chrome Debug

有了以上幾種調試方式,咱們幾乎能夠和常規的 Native 開發同樣來調試 RN 代碼了,不得不說 RN Team 確實牛 x 啊!

9、從 JS 調用 Native 方法或顯示自定義 Native View

這又是另外一個牛 x 之處啊。

不少人以爲 RN 限制太多,只能支持有限的 View 組件和有限的方法,難以發揮 Client 的最大性能。簡單點說,在 Client 能夠繪製複雜的 View,能夠調用高性能 C++ 等底層代碼,但 RN 卻作不到。

因而,RN 裏提出了 Native Modules 和 Native UI Component 兩種技術。

Native Modules:JS 裏直接調用 Native(Java/Swift) 方法

所謂 Native Modules,就是本身在 Client 寫好了某些方法,因爲某些緣由這些方法不太方便或者沒法搬到 RN 裏面,那麼,咱們能夠在 Client 把這些方法暴露出來給 RN,而後在 JS 裏能夠像 import 普通的 module 同樣把這些 Native Modules 引入進去,直接調用。

具體的實現方法能夠參考文檔 iOS Native Modules 和 Android Native Modules

Native UI Component:JS 裏直接調用自定義的 Native View

不少時候咱們在寫 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 代碼上來

10、React Native 適合你嗎?

這裏借鑑下前段時間舊金山的 React Native 會議上的一些優劣總結給讀者以參考。固然不必定對,僅供參考。

RN 的優勢:

  • 跨平臺
  • 原生的用戶體驗
  • 開發者體驗好
  • 動態更新代碼邏輯
  • 社區強大
  • 有個好爹

RN 的缺點:

  • 不夠成熟
  • 不夠穩定
  • 生態系統在搭建中
  • 優質的 App 須要時間打磨
  • 偶爾須要寫 Native 代碼(也就是 JS + Swift + Java)

適合下面這些人/公司:

  • 你對 JS/React 有必定了解
  • Web 開發人員比 Mobile 開發人員多
  • 有意願投資精力給 RN
  • App 設計不是特別區分 Android 和 iOS
  • 但願熱更新

下面這些人要稍微考慮下:

  • 徹底不瞭解 JS/React
  • 已經有現成的 Android/iOS team
  • App 設計嚴格遵照 Android、iOS各自設計規範
  • 不想要投入時間/金錢給 RN

11、爲何要寫這篇文章

幾個月前我對 React Native 也很是不看好,固然如今也沒有說很是看好。或者說,寫這篇文章毫無爲 React Native 佈道之意。

接觸 React Native 主要是由於業務須要,PM 但願可以隨時改動某塊變化較大的模塊,常規的開發提交流程每每須要較長的時間,而熱修復技術自己並未獲得 Google 和 Apple 的官方承認,也就是隨時可能因破壞生態安全之名被取締。

所以才考慮去了解 Hybrid 開發和 JS Native 開發模式,在瞭解過程當中,又因爲性能差、用戶體驗很差而放棄 Hybrid,因爲社區不完善、Bug 較多等緣由放棄 Weex,最終才選擇了 React Native,開始學習 React、JSX等語法。

目前使用下來對 React Native 的一些我的感覺:

  1. 學習門檻並無開始想象那麼高。大概只花了兩三天時間就熟悉了 Javascript、React 框架、JSX語法,而後就開始着手業務開發。
  2. 對 Android App 的影響。React Native 會給 Android 端帶來 6MB 左右的 size 增幅,不過在採用了 split apk 後就只有 1MB 左右增幅。
  3. Debug 功能比較完善,至少不用擔憂發生問題後不知從哪下手。
  4. 性能還行。最初擔憂的是 React Native 性能很差,但本身上手後,並無明顯感受到很明顯的 React Native 對 App 性能的負面影響,不管是 iOS 仍是 Android,固然,這一點還在繼續考察中。
  5. 動態部署真的很不錯。之前每次寫好代碼都要花很多時間來編譯運行,而如今只要寫一份代碼,就能夠同時在 Android 和 iOS 實時更新了,這無疑節省了生命。
  6. 有待完善。固然,React Native 中確實還存在着很多問題,生態系統也還不夠完善。不過我相信,這只是時間問題。

關於React Native一直以來都有不少爭議。

不過我想說的是,React Native 所表明的跨平臺、動態更新技術已經引發了全世界開發者關注,並且這種技術勢必會是將來的需求和潮流。React Native 不必定會成功,但至少目前 React Native 已是這一領域的領跑者。

而寫這篇文章的目的,就是但願告訴更多開發者,React Native 並不完美,但值得一試。

謝謝。

相關文章
相關標籤/搜索