本系列文章作為學(xué)習(xí)RN期間的總結(jié)
- React Native如何集成到現(xiàn)有項(xiàng)目中
- React Native和Native間的通信
- RCTRootView、RCTBridge做了什么
雖然ReactNative能做到iOS和Android的大部分邏輯共享一套代碼,節(jié)約開發(fā)成本;擁有像JSPatch那樣的熱修復(fù)功能,為線上問題提供非常靈活的解決方案。但是為什么大部分公司還是持觀望態(tài)度,或者只在產(chǎn)品的某些部分用RN進(jìn)行開發(fā)呢?
首先,React Native官方的某些組件仍然存在性能瓶頸,開發(fā)復(fù)雜場(chǎng)景的時(shí)候可能會(huì)遇到性能問題,像ListView,動(dòng)不動(dòng)就渲染整個(gè)視圖,雖然推出了FlatList但是也存在著一些其他的Bug。其次,RN的周邊生態(tài)并不完善,很多OC或Swift上已有的Library在NR上需要通過RN提供的方法重新用JS實(shí)現(xiàn)或者需要把這些庫(kù)橋接到RN。因此大部分公司會(huì)選擇交互不多,頁(yè)面不太復(fù)雜的場(chǎng)景來(lái)嘗試。本章,主要介紹如果在已有的App中集成React Native。
關(guān)鍵步驟
- 設(shè)置RN的依賴和目錄結(jié)構(gòu)
- 搞清楚你要在你的項(xiàng)目中使用的RN組件
- 使用CocoaPods添加你要使用的RN組件的依賴
- 使用npm安裝JS組件
- 在JavaScript環(huán)境下,開發(fā)你的RN模塊
- 添加一個(gè)
RCTRootView到你的app。它將會(huì)作為容器展示你的RN模塊。 - 啟動(dòng)RN服務(wù),Run你的App。
前置條件:安裝Node、npm最新版本(npm是基于Node實(shí)現(xiàn)的包管理工具和iOS的CocoaPod地位相當(dāng))
設(shè)置RN的依賴和目錄結(jié)構(gòu)
為React Native項(xiàng)目創(chuàng)建一個(gè)新的文件夾,在文件夾中新建/ios目錄,拷貝所有原項(xiàng)目的內(nèi)容到/ios目錄下。
安裝JavaScript依賴
在剛剛新建的文件夾中(即根目錄中)創(chuàng)建一個(gè)package.json文件,并添加一下內(nèi)容:
{
"name": "Snapvote",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "16.0.0-alpha.12",
"react-native": "0.48.4",
"react-native-vector-icons": "^4.4.2",
"whatwg-fetch": "^2.0.3"
},
"devDependencies": {
"babel-jest": "21.2.0",
"babel-preset-react-native": "4.0.0",
"jest": "21.2.0",
"react-test-renderer": "16.0.0-alpha.12"
},
"jest": {
"preset": "react-native"
}
}
接下去,安裝react和react-native包。打開Terminal,在你項(xiàng)目的根目錄下面執(zhí)行下面命令:
npm install --save r16.0.0-alpha.12 react-native
要確保這里安裝的版本和package.json里說明的版本一致
執(zhí)行這個(gè)命令之后,將會(huì)在項(xiàng)目的根目錄下創(chuàng)建一個(gè)/node_modules的目錄,這里保存著所有你項(xiàng)目中所需的JavaScript依賴。
安裝CocoaPods
這里就不說了
配置CocoaPods依賴
在你集成RN到你項(xiàng)目中之前,你需要選擇你要使用的React Native庫(kù)。你將通過CocoaPod庫(kù)的開發(fā)模式將其集成進(jìn)去。

這些庫(kù)的
subspec文件都會(huì)在/node_modules目錄下被說明,最后執(zhí)行pod install命令,所有的React Native庫(kù)依賴到這里就都準(zhǔn)備好了。
業(yè)務(wù)代碼
-
創(chuàng)建
index.js文件
在項(xiàng)目的根目錄下創(chuàng)建index.js文件,這個(gè)文件是你RN項(xiàng)目的
入口,所有在Native中要用到的RN模塊都在這里面進(jìn)行注冊(cè)。例如項(xiàng)目中的投票列表、設(shè)置頁(yè)面等。各個(gè)模塊的名稱要和Native中的模塊名稱對(duì)應(yīng)。
rn_modul 添加React Native 代碼(JavaScript和CSS)
'use strict';
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
FlatList,
NativeModules,
Image,
ActivityIndicator,
TouchableOpacity,
ScrollView,
Switch,
TouchableWithoutFeedback,
Alert,
NativeEventEmitter,
} from 'react-native';
import StarRatingView from './starRating.view.js'
var { width, height } = require('Dimensions').get('window');
var nativeModuleManager = NativeModules.XYRCTBrigeModule;
class SettingsView extends React.PureComponent{
constructor(props){
super(props);
}
.....
.....
在Native中使用RCTRootView作為RN模塊的容器。所有通過RN渲染出來(lái)的視圖都會(huì)展示在該View上。
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
{{< hl-text green >}}//設(shè)置獲取JavaScript文件的路徑,從服務(wù)器或者本地文件獲取{{< /hl-text >}}
#if DEBUG
jsCodeLocation = [NSURL URLWithString:@"http://10.0.30.119:8081/index.ios.bundle?platform=ios"];
#else
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
#endif
{{< hl-text green >}}//通過URL、模塊名稱加載對(duì)應(yīng)的RN視圖,生成一個(gè)OC對(duì)象`RCTRootView`,最后將該View添加到controller的View上{{< /hl-text >}}
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"TabberView"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
到這里就完成了一個(gè)簡(jiǎn)單React Native App的集成。
測(cè)試
- 因?yàn)镠TTPS的限制,請(qǐng)將Domain添加到
Info.plist的白名單
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
- 執(zhí)行
npm start開啟本地服務(wù) - Xcode run.
