iOS原生專案整合 React Native 一 導航
先來看一下完整效果
整合 RN 的步驟請參照 官方文件。
這裡注意一下專案的目錄結構,所有 RN 相關均在 ReactNative
目錄下。
相應地,podfile
和 package.json
要做一下相應調整。
podfile
platform:ios,'8.0'
def native_pods
pod 'JLRoutes', '2.1'
end
def react_pods
pod 'React', :path => './ReactNative/node_modules/react-native', :subspecs => [
'Core',
'ART',
'RCTActionSheet',
'RCTAdSupport',
'RCTGeolocation',
'RCTImage',
'RCTNetwork',
'RCTPushNotification',
'RCTSettings',
'RCTText',
'RCTVibration',
'RCTWebSocket',
'RCTLinkingIOS',
'RCTAnimation',
'DevSupport'
]
pod "Yoga", :path => "./ReactNative/node_modules/react-native/ReactCommon/yoga"
end
target 'CCDemo' do
native_pods
react_pods
end
如果執行報錯 如 'RCTAnimation/RCTValueAnimatedNode.h' file not found.
,則將#import <RCTAnimation/RCTValueAnimatedNode.h> 改成 #import "RCTValueAnimatedNode.h"
package.json
{
"name": "CCDemo",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"bundle": "^2.1.0",
"react": "16.0.0-alpha.6",
"react-native": "0.44.3",
"react-navigation": "^1.0.0-beta.26"
}
}
好了,下面來寫兩個 RN 頁面
新建 RN1Scene.js RN2Scene.js App.js
export default class RN1Scene extends Component {
constructor(props) {
super(props);
const {
navigation,
} = this.props;
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Text style={styles.instructions} onPress={()=>navigate('RN2Scene')}>To RN2Scene</Text>
</View>
);
}
}
export default class RN2Scene extends Component {
handleOnPress() {
console.log('To Native2')
}
render() {
return (
<View style={styles.container}>
<Text style={styles.instructions} onPress={this.handleOnPress}>To Native2</Text>
</View>
);
}
}
由 App.js
統一管理 RN Scene
先來測試一下RN部分程式碼是否可行,
ViewController
中
- (IBAction)ToRN1Scene:(id)sender {
NSURL *jsCodeLocation = [NSURL
URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL : jsCodeLocation
moduleName : @"DemoRN"
initialProperties : nil
launchOptions : nil];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self.navigationController pushViewController:vc animated:YES];
}
現在已經完成了 Native -> RN1 -> RN2。同時也會出現幾個問題,
- 導航欄
- 首頁的返回按鈕
- 返回手勢
對於導航欄,由於RN使用的NavigationBar 與原生同時存在,有可能原生導航欄會覆蓋在 RN 上,有部分應用可能隱藏了系統導航欄,使用自定義的 View,則不存在這個問題,這裡只需要在 RN 頁面隱藏原生導航欄即可。至於 RN 部分是繼續自定義還是使用 StackNavigator
就看大家選擇了。
隱藏了原生NavigationBar會帶來第二個問題,進入RN1Scene時,返回按鈕沒有了。這時需要自己實現pop功能。
我們看到呈現的 RN1Scene 和 RN2Scene 都承載到一個 ViewController 中,無論在哪個 Scene 使用返回手勢,都會返回到原生頁面。
下面需要進行原生部分的工作
新建 bridge 檔案,
這裡寫一個原生返回方法,一個原生跳轉方法供 RN 使用
@implementation CCRNBridge
RCT_EXPORT_MODULE(RNBridge)
/// UI 相關 需寫在主執行緒
RCT_EXPORT_METHOD(pushToVC:(NSString *)vc paramters:(NSDictionary *)para)
{
dispatch_async(dispatch_get_main_queue(), ^{
[[CCRouterManager sharedInstance] pushToVC:vc paramters:para];
});
}
RCT_EXPORT_METHOD(popViewController:(BOOL)animated)
{
dispatch_async(dispatch_get_main_queue(), ^{
[[CCRouterManager sharedInstance] popViewController:animated];
});
}
/// RN 使用的引數,可以傳方法或者常量
- (NSDictionary *)constantsToExport {
return @{
@"baseurl" : @"someurl"
};
}
@end
在 RN2Scene 加入如下程式碼:
import {
NativeModules
} from 'react-native';
var Native = NativeModules.RNBridge;
'''
handleOnPress() {
Native.pushToVC('CCOneController',{labelText:'From RN2'})
}
'''
到這裡已經完成了 已經完成了 Native -> RN1 -> RN2 -> Native。
現在總結一下現有的跳轉方式
-- | -- |
---|---|
Native -> Native | Router |
RN -> RN | StackNavigator |
RN -> Native | Router |
還有一種 Native -> RN 這種還是使用比較原始的方法,我們可以再封裝一層,統一使用 Router 的方式跳轉。
新建 統一的 Container
@interface CCRNContainer : CCBaseViewController
@property (nonatomic, strong) NSString *moduleName;
@property (nonatomic, strong) NSString *bundlePath;
@property (nonatomic, strong) NSDictionary *paramters;
@end
@implementation CCRNContainer
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *jsCodeLocation = [NSURL
URLWithString:self.bundlePath];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL : jsCodeLocation
moduleName : self.moduleName
initialProperties : self.paramters
launchOptions : nil];
self.view = rootView;
}
@end
ViewController 中
- (IBAction)ToRN1Scene:(id)sender {
NSDictionary *para = @{
@"moduleName" : @"DemoRN",
@"bundlePath" : @"http://localhost:8081/index.ios.bundle?platform=ios",
};
[[CCRouterManager sharedInstance] pushToVC:@"CCRNContainer" paramters:para];
}
至此,我們的幾種跳轉方式已經統一了。
相關文章
- React Native整合到現有的原生專案React Native
- 原生專案如何從零開始整合 React NativeReact Native
- React Native 導航:示例教程React Native
- 從零開始生成一個ios react-native專案iOSReact
- iOS原生專案中整合flutter初試iOSFlutter
- 建立一個react-native專案(2/4)React
- 整合 React Native 到現有的 Android 專案( Mac, Windows 通用版 )React NativeAndroidMacWindows
- [譯] 原生 iOS(Swift) 和 React-Native 的效能比較iOSSwiftReact
- React-Native專案總結React
- 記一次iOS自動化打包走過的坑-關於React Native-iOS專案iOSReact Native
- React Native --踩坑記 之 建立指定 React Native版本的專案React Native
- 如何在React Native專案中整合華為遠端配置服務React Native
- React Native 整合code pushReact Native
- React Native 橋接原生 iOS 以及 Android 獲取 APP 版本號React Native橋接iOSAndroidAPP
- react-native 修改專案名稱React
- react native社群專案知識點React Native
- React Native在Android當中實踐(三)——整合到Android專案當中React NativeAndroid
- react-native 仿原生自定義彈窗|iOS/Android 彈窗效果ReactiOSAndroid
- React Native學習指南:React Native嵌入到原生應用的一次嘗試React Native
- (零) React Native 專案開發拾遺React Native
- 如何在 React Native 專案中使用 MQTTReact NativeMQQT
- Practice – iOS 專案持續整合實踐(一)iOS
- Practice - iOS 專案持續整合實踐(一)iOS
- React專案整合Immutable.jsReactJS
- React Native專案自動化打包釋出React Native
- React-Native iOS Module開發ReactiOS
- 在Android原生專案中整合FlutterAndroidFlutter
- [混編] iOS原生專案- 接入FlutteriOSFlutter
- 為現有iOS專案整合FlutteriOSFlutter
- 利用TypeScript構建優雅的React Native專案TypeScriptReact Native
- React-Native入門(1)-專案工程初識React
- 使用React Native和Expo快速構建原生移動iOS和Android應用程式React NativeiOSAndroid
- 探索 react-native run-ios(android)ReactiOSAndroid
- ? React-Native 官方示例演示 ( ios & android)ReactiOSAndroid
- [混編] iOS原生專案- iOS/flutter 程式碼互動iOSFlutter
- 【3月更新】React Native 優秀開源專案大全React Native
- Angular專案路由配置與導航守衛Angular路由
- React Native iOS混合開發實戰教程React NativeiOS
- [譯] React Native 與 iOS 和 Android 通訊React NativeiOSAndroid