1. 程式人生 > >React Native 混合開發與實現

React Native 混合開發與實現

關於

  • 微信公眾號:前端呼啦圈(Love-FED)
  • 我的部落格:勞卜的部落格
  • 知乎專欄:前端呼啦圈

前言

隨著 React 的盛行,其移動開發框架 React Native 也收到了廣大開發者的青睞,以下簡稱 RN。通過 RN 我們能夠使用 JavaScript 語言來實現跨平臺移動應用的開發,打開了前端工程師通往移動平臺的大門。用 RN 官方的介紹來概括它的特點就是:Learn once, write anywhere

如果你瞭解 React,那麼學習 RN 的話應該會非常輕鬆。因為 RN 和 React 使用了相同的開發語言 JavaScript 和相同的設計理念 React,在 React 的基礎上添加了原生平臺的底層支援。這樣,不同平臺的適配就交由 RN 去處理,而開發者只需要關注 RN 平臺應用開發本身。

本文將從 RN 混合開發(與 iOS、Android 平臺互動)的原理和實現進行介紹,結合流程圖的方式讓大家進一步的瞭解 RN 開發的思想和底層邏輯。

原理與實現

1. 從 Hello world 開始

先來看一個使用 RN 實現的簡單的 Hello world 展示:

上方我們不難看到一些很熟悉的 React 語法,但除此之外我們還能看到其引入了 react-native 庫中的 AppRegistry API 和 Text (文字)元件,這便是 RN 提供給我們用於呼叫原生平臺的 APIs 和 元件,其能夠在不同移動裝置上實現一致的功能和邏輯。最後展示在 APP 中的便是 Hello world 文字,而至於 AppRegistry API 後面會做相應介紹。

2. 解刨 React Native 應用的結構

那麼看完 Hello world 示例後,我們應該大致知道了 RN 應用的一個結構,我們用圖例的方式進行解刨說明,如下圖所示:

從圖中可以看到,我們整個的 RN 應用可以分為兩層展示:

  • JavaScript Code 層
  • Native Code 層

也可以理解為所謂的應用層和底層。應用層通過 JavaScript 橋接層 與底層平臺進行互動,獲取底層平臺的原生 APIs、UI 元件及一些自定義元件等。比如 Hello world 示例中引入的 AppRegistry API 和 Text 元件便是很好的說明。
這樣的分層能夠使應用層的開發變得簡單、高效和跨平臺,對於應用的穩定性、執行時的效能來說將和原生平臺保持接近。

3. 原生平臺呼叫 React Native 元件

大致瞭解完 React Native 應用的結構後,我們不妨再來認識下原生平臺是如何呼叫 React Native 元件的。我們 RN 的程式碼要跑在原生 APP 中那必然需要原生 APP 載入執行對應的 RN 元件,以實現混合開發和互動的功能。這裡就要來介紹下剛剛擱置的 AppRegistry API 了。

一般我們的 RN 專案都會有一個入口檔案,比如 index.js(老版本會存在兩個:index.ios.js 和 index.android.js)用於註冊根元件並提供給原生平臺執行。這裡的註冊根元件就要通過 AppRegistry API 來實現。


我們需要在根元件裡呼叫 AppRegistry 中的 registerComponent 方法進行元件的註冊。註冊完之後原生平臺便可以通過 runApplication 方法來執行註冊過的根元件。需要注意的是註冊和執行的元件名稱兩者必須保持一致,這樣才能夠實現載入對應的元件。比如 Hello world 示例中我們註冊的根元件名為 HelloWorldApp,並且注入相應的元件模組。另外同時一個入口檔案中,我們也可以註冊多個根元件。

4. 原生載入 React Native 介面

剛剛在介紹原生平臺呼叫 RN 元件時提到了載入對應根元件的功能。那麼是不是原生平臺只有通過不斷的呼叫執行 RN 註冊的根元件才能實現不同頁面的首次載入呢(這裡的載入指原生開啟 RN 頁面)?答案是否定的。

除了上述通過呼叫不同的根元件來實現原生開啟不同的 RN 介面外(圖中第二點),我們還可以呼叫一個根元件來實現。唯一的區別在於我們需要呼叫時在 initialProperties 中新增區分不同介面的標識位來渲染不同的元件,就好比在 URL 上攜帶不同引數跳轉到同一路由一樣,根據路由上的引數在應用層進行對應元件的渲染。

在 RN 根元件中我們可以通過 this.props 獲取原生平臺攜帶過來的引數物件,如示例中的 viewName,再根據 viewName 實現 RN 內部元件的渲染,當然也可以結合 react-navigation 來實現路由模組的切換。至於最終選擇哪種方式載入,決定權還是要看業務的劃分和功能的定義。相比較而言第一種可能更加靈活和便捷。

5. React Native 與原生平臺通訊原理

在混合開發模式下,我們不可避免的需要和原生平臺進行資料的通訊,那麼在 RN 中,我們如何與原生平臺進行通訊呢?如何獲取原生平臺提供的資料或將資料傳遞給原生平臺呢?下面這張圖便介紹了這一流程。

在 RN 中,我們可以引用 react-native 模組中的 NativeModules API 來進行資料通訊,呼叫的方法是 NativeModules.模組名稱.介面名稱,而原生平臺返回資料到 RN 平臺是基於回撥,程式碼如下:

import { NativeModules } from 'react-native';
const userInfo = NativeModules.UserInfo; // 獲取自定義使用者資訊模組
console.log(userInfo.userName); // 列印使用者名稱
const router = NativeModules.Router; // 獲取自定義路由模組
// 呼叫原生路由跳轉方法
router.openHome('引數', (res) => {
    console.log(res); // 列印返回資料
});

通過 NativeModules 我們可以靈活的獲取或傳遞資料給原生平臺,同時我們也可以根據業務需要編寫不同的 Bridge 方法來實現資料通訊模組的封裝,比如使用者資訊模組、路由跳轉模組及網路請求模組等。

6. Redux 架構

在 RN 專案中,除了與原生平臺通訊和互動的功能外,RN 平臺自身也需要實現一些資料狀態的管理。這裡我們還得認識下 Redux 架構。

 

 

Redux 是一個用於管理 React 應用狀態的容器,在 RN 中也同樣適用。其採用單一資料流的方式來實現資料的管理,唯一改變 state 的方法是提交 action 操作。這樣的架構使得我們的 RN 專案資料易於維護或擴容,改變資料的流程容易追蹤和捕獲。需要了解的具體關鍵字如下:

 

具體文件可以參考:http://cn.redux.js.org/
當然你也可以使用其他第三方庫實現類似的架構,比如 mobx、dva 等。

7. CSS-in-JS

除了 Redux 架構,RN 中還加入了 CSS in JS 的概念,將原本關注點分離的理念轉移到了關注點混合上,使得我們可以在 JS 中寫 CSS 程式碼,但這並不違背之前關注點分離的理念。

現在隨著元件化概念的流行,對從元件層面維護 CSS 樣式的需求日益增大,CSS-in-JS 就是在元件內部使用 JavaScript 對 CSS 進行了抽象,可以對其宣告和加以維護。這樣不僅降低了編寫 CSS 樣式帶來的風險,也讓開發變得更加輕鬆。它和 CSS Modules 的區別是不再需要 CSS 樣式檔案。

結合 JSX 語法,在 RN 中書寫和維護 CSS 變得更加便捷,也是 Web 元件化不斷髮展的必然產物。

8. React Native 中 的 Flex 佈局

另外,在開發 RN 專案時,官方推薦使用的佈局方式是 Flex 佈局,因為 Flexbox 可以在不同螢幕尺寸上提供一致的佈局結構,這也解決了跨平臺佈局呈現的問題。

相比我們客戶端使用的 Flex 佈局,RN 中的 Flex 佈局有稍許的不同,比如 flexDirection 的預設值是 column 而不是 row,flex 也只能指定一個數字值等。關於 Flex 佈局的介紹可以參考:Flex 佈局教程:語法篇、Flex 佈局教程:例項篇

9. React Native 的熱部署

最後我們介紹下 RN 中的熱部署,這也是選擇 RN 開發 APP 的一個重要原因之一。相比傳統 APP 更新,大都需要第三方稽核的流程,而這個流程可能會很慢或者不及時,遇到需要緊急修復的 bug 無法及時更新而導致直接的經濟損失是很常見的問題,而 RN 的熱部署可以一定程度上解決或減輕這一問題的影響。那麼其實現原理是怎樣的呢?

上圖左側部分便展現了使用者訪問 RN 應用的熱部署流程。首先使用者訪問 APP,APP 會向 RN 伺服器請求資源包,如果資源包未更新則讀取本地快取資源,如果開發者為了解決 bug 重新更新了伺服器上的資源包,那麼 APP 拉去後會快取起來,待使用者下次進入後再進行更新。這便是 RN 熱部署的流程。

在本地開發時,我們不難發現當我們在執行起來的 RN 專案中修改程式碼時,再次從 APP 進入 RN 頁面,本地終端會再次載入一次更新後的資源資料,這也是 RN 熱部署的體現。

同樣線上的熱部署則需要將我們打包後的 RN 資源上傳到伺服器上供 APP 讀取來實現。

我們可以手動執行打包、上傳發布流程,當然為了減少人為干預,實現前端自動化,我們也可以把這塊流程交給構建平臺去自動打包部署,這便需要搭建一個後臺系統進行管理。

結語

本文介紹了 React Native 混合開發的原理與實現邏輯。只有先了解原理,才能高效的投入專案的開發中,而關於 RN 自身的功能實現大家可以直接閱讀官方文件,這裡我也額外提供一些關於 RN 的參考資料:

  • React-Native學習指南
  • 分享 50 個完整的 React Native 專案
  • 給所有開發者的React Native詳細入門指南
  • 30天學習React Native教程

注:本文部分圖例參考自《React Native 移動開發實戰》一書