React Native 混合開發(fā)與實現(xiàn)

前言

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

如果你了解 React,那么學(xué)習 RN 的話應(yīng)該會非常輕松丑勤。因為 RN 和 React 使用了相同的開發(fā)語言 JavaScript 和相同的設(shè)計理念 React华嘹,在 React 的基礎(chǔ)上添加了原生平臺的底層支持。這樣法竞,不同平臺的適配就交由 RN 去處理耙厚,而開發(fā)者只需要關(guān)注 RN 平臺應(yīng)用開發(fā)本身强挫。

本文將從 RN 混合開發(fā)(與 iOS、Android 平臺交互)的原理和實現(xiàn)進行介紹薛躬,結(jié)合流程圖的方式讓大家進一步的了解 RN 開發(fā)的思想和底層邏輯俯渤。

原理與實現(xiàn)

1. 從 Hello world 開始

先來看一個使用 RN 實現(xiàn)的簡單的 Hello world 展示:

上方我們不難看到一些很熟悉的 React 語法,但除此之外我們還能看到其引入了 react-native 庫中的 AppRegistry API 和 Text (文本)組件型宝,這便是 RN 提供給我們用于調(diào)用原生平臺的 APIs 和 組件八匠,其能夠在不同移動設(shè)備上實現(xiàn)一致的功能和邏輯。最后展示在 APP 中的便是 Hello world 文本趴酣,而至于 AppRegistry API 后面會做相應(yīng)介紹梨树。

2. 解刨 React Native 應(yīng)用的結(jié)構(gòu)

那么看完 Hello world 示例后,我們應(yīng)該大致知道了 RN 應(yīng)用的一個結(jié)構(gòu)价卤,我們用圖例的方式進行解刨說明劝萤,如下圖所示:

從圖中可以看到渊涝,我們整個的 RN 應(yīng)用可以分為兩層展示:

  • JavaScript Code 層
  • Native Code 層

也可以理解為所謂的應(yīng)用層和底層慎璧。應(yīng)用層通過 JavaScript 橋接層 與底層平臺進行交互,獲取底層平臺的原生 APIs跨释、UI 組件及一些自定義組件等胸私。比如 Hello world 示例中引入的 AppRegistry API 和 Text 組件便是很好的說明。

這樣的分層能夠使應(yīng)用層的開發(fā)變得簡單鳖谈、高效和跨平臺岁疼,對于應(yīng)用的穩(wěn)定性、運行時的性能來說將和原生平臺保持接近缆娃。

3. 原生平臺調(diào)用 React Native 組件

大致了解完 React Native 應(yīng)用的結(jié)構(gòu)后捷绒,我們不妨再來認識下原生平臺是如何調(diào)用 React Native 組件的。我們 RN 的代碼要跑在原生 APP 中那必然需要原生 APP 加載運行對應(yīng)的 RN 組件贯要,以實現(xiàn)混合開發(fā)和交互的功能暖侨。這里就要來介紹下剛剛擱置的 AppRegistry API 了。

一般我們的 RN 項目都會有一個入口文件崇渗,比如 index.js(老版本會存在兩個:index.ios.js 和 index.android.js)用于注冊根組件并提供給原生平臺運行字逗。這里的注冊根組件就要通過 AppRegistry API 來實現(xiàn)。

我們需要在根組件里調(diào)用 AppRegistry 中的 registerComponent 方法進行組件的注冊宅广。注冊完之后原生平臺便可以通過 runApplication 方法來運行注冊過的根組件葫掉。需要注意的是注冊和運行的組件名稱兩者必須保持一致,這樣才能夠?qū)崿F(xiàn)加載對應(yīng)的組件跟狱。比如 Hello world 示例中我們注冊的根組件名為 HelloWorldApp俭厚,并且注入相應(yīng)的組件模塊。另外同時一個入口文件中驶臊,我們也可以注冊多個根組件。

4. 原生加載 React Native 界面

剛剛在介紹原生平臺調(diào)用 RN 組件時提到了加載對應(yīng)根組件的功能。那么是不是原生平臺只有通過不斷的調(diào)用運行 RN 注冊的根組件才能實現(xiàn)不同頁面的首次加載呢(這里的加載指原生打開 RN 頁面)柔滔?答案是否定的电媳。

除了上述通過調(diào)用不同的根組件來實現(xiàn)原生打開不同的 RN 界面外(圖中第二點),我們還可以調(diào)用一個根組件來實現(xiàn)但绕。唯一的區(qū)別在于我們需要調(diào)用時在 initialProperties 中添加區(qū)分不同界面的標識位來渲染不同的組件,就好比在 URL 上攜帶不同參數(shù)跳轉(zhuǎn)到同一路由一樣,根據(jù)路由上的參數(shù)在應(yīng)用層進行對應(yīng)組件的渲染症副。

在 RN 根組件中我們可以通過 this.props 獲取原生平臺攜帶過來的參數(shù)對象,如示例中的 viewName政基,再根據(jù) viewName 實現(xiàn) RN 內(nèi)部組件的渲染贞铣,當然也可以結(jié)合 react-navigation 來實現(xiàn)路由模塊的切換。至于最終選擇哪種方式加載沮明,決定權(quán)還是要看業(yè)務(wù)的劃分和功能的定義辕坝。相比較而言第一種可能更加靈活和便捷。

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

在混合開發(fā)模式下荐健,我們不可避免的需要和原生平臺進行數(shù)據(jù)的通信酱畅,那么在 RN 中,我們?nèi)绾闻c原生平臺進行通信呢江场?如何獲取原生平臺提供的數(shù)據(jù)或?qū)?shù)據(jù)傳遞給原生平臺呢纺酸?下面這張圖便介紹了這一流程。

在 RN 中址否,我們可以引用 react-native 模塊中的 NativeModules API 來進行數(shù)據(jù)通信餐蔬,調(diào)用的方法是 NativeModules.模塊名稱.接口名稱,而原生平臺返回數(shù)據(jù)到 RN 平臺是基于回調(diào)佑附,代碼如下:

import { NativeModules } from 'react-native';

const userInfo = NativeModules.UserInfo; // 獲取自定義用戶信息模塊

console.log(userInfo.userName); // 打印用戶名

const router = NativeModules.Router; // 獲取自定義路由模塊

// 調(diào)用原生路由跳轉(zhuǎn)方法
router.openHome('參數(shù)', (res) => {
    console.log(res); // 打印返回數(shù)據(jù)
});

通過 NativeModules 我們可以靈活的獲取或傳遞數(shù)據(jù)給原生平臺樊诺,同時我們也可以根據(jù)業(yè)務(wù)需要編寫不同的 Bridge 方法來實現(xiàn)數(shù)據(jù)通信模塊的封裝,比如用戶信息模塊音同、路由跳轉(zhuǎn)模塊及網(wǎng)絡(luò)請求模塊等词爬。

6. Redux 架構(gòu)

在 RN 項目中,除了與原生平臺通信和交互的功能外瘟斜,RN 平臺自身也需要實現(xiàn)一些數(shù)據(jù)狀態(tài)的管理缸夹。這里我們還得認識下 Redux 架構(gòu)。

Redux 是一個用于管理 React 應(yīng)用狀態(tài)的容器螺句,在 RN 中也同樣適用虽惭。其采用單一數(shù)據(jù)流的方式來實現(xiàn)數(shù)據(jù)的管理,唯一改變 state 的方法是提交 action 操作蛇尚。這樣的架構(gòu)使得我們的 RN 項目數(shù)據(jù)易于維護或擴容芽唇,改變數(shù)據(jù)的流程容易追蹤和捕獲。需要了解的具體關(guān)鍵字如下:

具體文檔可以參考:http://cn.redux.js.org/

當然你也可以使用其他第三方庫實現(xiàn)類似的架構(gòu),比如 mobx匆笤、dva 等研侣。

7. CSS-in-JS

除了 Redux 架構(gòu),RN 中還加入了 CSS in JS 的概念炮捧,將原本關(guān)注點分離的理念轉(zhuǎn)移到了關(guān)注點混合上庶诡,使得我們可以在 JS 中寫 CSS 代碼,但這并不違背之前關(guān)注點分離的理念咆课。

現(xiàn)在隨著組件化概念的流行末誓,對從組件層面維護 CSS 樣式的需求日益增大,CSS-in-JS 就是在組件內(nèi)部使用 JavaScript 對 CSS 進行了抽象书蚪,可以對其聲明和加以維護喇澡。這樣不僅降低了編寫 CSS 樣式帶來的風險,也讓開發(fā)變得更加輕松殊校。它和 CSS Modules 的區(qū)別是不再需要 CSS 樣式文件晴玖。

結(jié)合 JSX 語法,在 RN 中書寫和維護 CSS 變得更加便捷为流,也是 Web 組件化不斷發(fā)展的必然產(chǎn)物呕屎。

8. React Native 中 的 Flex 布局

另外,在開發(fā) RN 項目時艺谆,官方推薦使用的布局方式是 Flex 布局榨惰,因為 Flexbox 可以在不同屏幕尺寸上提供一致的布局結(jié)構(gòu),這也解決了跨平臺布局呈現(xiàn)的問題静汤。

相比我們客戶端使用的 Flex 布局,RN 中的 Flex 布局有稍許的不同居凶,比如 flexDirection 的默認值是 column 而不是 row虫给,flex 也只能指定一個數(shù)字值等。關(guān)于 Flex 布局的介紹可以參考:Flex 布局教程:語法篇侠碧、Flex 布局教程:實例篇

9. React Native 的熱部署

最后我們介紹下 RN 中的熱部署抹估,這也是選擇 RN 開發(fā) APP 的一個重要原因之一。相比傳統(tǒng) APP 更新弄兜,大都需要第三方審核的流程药蜻,而這個流程可能會很慢或者不及時,遇到需要緊急修復(fù)的 bug 無法及時更新而導(dǎo)致直接的經(jīng)濟損失是很常見的問題替饿,而 RN 的熱部署可以一定程度上解決或減輕這一問題的影響语泽。那么其實現(xiàn)原理是怎樣的呢?

上圖左側(cè)部分便展現(xiàn)了用戶訪問 RN 應(yīng)用的熱部署流程视卢。首先用戶訪問 APP踱卵,APP 會向 RN 服務(wù)器請求資源包,如果資源包未更新則讀取本地緩存資源据过,如果開發(fā)者為了解決 bug 重新更新了服務(wù)器上的資源包惋砂,那么 APP 拉去后會緩存起來妒挎,待用戶下次進入后再進行更新。這便是 RN 熱部署的流程西饵。

在本地開發(fā)時酝掩,我們不難發(fā)現(xiàn)當我們在運行起來的 RN 項目中修改代碼時,再次從 APP 進入 RN 頁面眷柔,本地終端會再次加載一次更新后的資源數(shù)據(jù)庸队,這也是 RN 熱部署的體現(xiàn)。

同樣線上的熱部署則需要將我們打包后的 RN 資源上傳到服務(wù)器上供 APP 讀取來實現(xiàn)闯割。

我們可以手動執(zhí)行打包彻消、上傳發(fā)布流程,當然為了減少人為干預(yù)宙拉,實現(xiàn)前端自動化宾尚,我們也可以把這塊流程交給構(gòu)建平臺去自動打包部署,這便需要搭建一個后臺系統(tǒng)進行管理谢澈。

結(jié)語

本文介紹了 React Native 混合開發(fā)的原理與實現(xiàn)邏輯煌贴。只有先了解原理,才能高效的投入項目的開發(fā)中锥忿,而關(guān)于 RN 自身的功能實現(xiàn)大家可以直接閱讀官方文檔牛郑,這里我也額外提供一些關(guān)于 RN 的參考資料:

注:本文部分圖例參考自《React Native 移動開發(fā)實戰(zhàn)》一書

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市敬鬓,隨后出現(xiàn)的幾起案子淹朋,更是在濱河造成了極大的恐慌,老刑警劉巖钉答,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件础芍,死亡現(xiàn)場離奇詭異,居然都是意外死亡数尿,警方通過查閱死者的電腦和手機仑性,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來右蹦,“玉大人诊杆,你說我怎么就攤上這事『温剑” “怎么了晨汹?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長甲献。 經(jīng)常有香客問我宰缤,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任慨灭,我火速辦了婚禮朦乏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘氧骤。我一直安慰自己呻疹,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布筹陵。 她就那樣靜靜地躺著刽锤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪朦佩。 梳的紋絲不亂的頭發(fā)上并思,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音语稠,去河邊找鬼宋彼。 笑死,一個胖子當著我的面吹牛仙畦,可吹牛的內(nèi)容都是我干的输涕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼慨畸,長吁一口氣:“原來是場噩夢啊……” “哼莱坎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寸士,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤檐什,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碉京,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厢汹,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年谐宙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片界弧。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡凡蜻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垢箕,到底是詐尸還是另有隱情划栓,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布条获,位于F島的核電站忠荞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜委煤,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一堂油、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碧绞,春花似錦府框、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至兴使,卻和暖如春系宜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背发魄。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工盹牧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欠母。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓欢策,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赏淌。 傳聞我的和親對象是個殘疾皇子踩寇,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容