React Native之集成到现有原生应用中(iOS)
2019-02-11 本文已影响3人
平安喜乐698
目录
1. iOS
<1>创建目录
首先创建一个空目录(根目录)用于存放 React Native 项目;
然后在其中创建一个ios子目录,把现有的 iOS 项目拷贝到ios子目录中;
<2>安装React 和 React Native 模块
在根目录下创建一个名为package.json的空文本文件,然后填入以下内容:
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
}
}
用 yarn 或 npm(两者都是 node 的包管理器)来安装 React 和 React Native 模块。(所有 JavaScript 依赖模块都会被安装到根目录下的node_modules目录中)
yarn add react-native 或 yarn add react@16.2.0
<3>配置CocoaPods,并安装
可用的subspec都列在node_modules/react-native/React.podspec中
必要的Core(含了必须的AppRegistry、StyleSheet、View以及其他的一些 React Native 核心库);
想使用 Text,则加入RCTText;
想使用 Image,则加入RCTImage;
等等
Podfile示例如下:
# platform :ios, '9.0'
target '项目名' do
# use_frameworks!
# 'node_modules'目录一般位于根目录中
# 但是如果你的结构不同,那你就要根据实际路径修改下面的`:path`
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'CxxBridge', # 如果RN版本 >= 0.47则加入此行
'DevSupport', # 如果RN版本 >= 0.43,则需要加入此行才能开启开发者菜单
'RCTText',
'RCTNetwork',
'RCTWebSocket', # 调试功能需要此模块
'RCTAnimation', # FlatList和原生动画功能需要此模块
# 在这里继续添加你所需要的其他RN模块
]
# 如果你的RN版本 >= 0.42.0,则加入下面这行
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
# 如果RN版本 >= 0.45则加入下面三个第三方编译依赖
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
end
<4>项目根目录下创建index.js
import React, { Component } from "react";
import {AppRegistry, StyleSheet, Text, View} from 'react-native';
class RNHighScores extends React.Component {
render() {
var contents = this.props['scores'].map((score) => (
<Text key={score.name}>
{score.name}:{score.value}
{'\n'}
</Text>
));
return (
<View style={styles.container}>
<Text style={styles.highScoresTitle}>2048 High Scores!</Text>
<Text style={styles.scores}>{contents}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
},
highScoresTitle: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
scores: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('RNHighScores', () => RNHighScores);
<5>ViewController中
#import <React/RCTRootView.h>
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
// moduleName和js组件名要一致
// initialProperties可以在js组件this.props['scores']获取,这一字典参数会在内部被转化为一个可供 JS 组件调用的 JSON 对象
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
moduleName: @"RNHighScores"
initialProperties:
@{
@"scores" : @[
@{
@"name" : @"Alex",
@"value": @"42"
},
@{
@"name" : @"Joel",
@"value": @"10"
}
]
}
launchOptions: nil];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self presentViewController:vc animated:YES completion:nil];
其他(略过)
rootView.appProperties = @{@"images" : @[@"",@""]};
1、设置appProperties之后,React Native 应用将会根据新的属性重新渲染(仅当新旧属性不一样时)。
2、必须在主线程中设置
3、如果在 bridge 还没初始化完成前就设置 appProperties,设置可能会无效
4、componentWillReceiveProps和componentWillUpdateProps方法在属性更新后不会触发。但可以通过componentWillMount访问新的属性值
rootView.delegate = self;
rootView.sizeFlexibility = RCTRootViewSizeFlexibilityHeight;
#pragma mark - RCTRootViewDelegate
- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView{
CGRect newFrame = rootView.frame;
newFrame.size = rootView.intrinsicContentSize;
rootView.frame = newFrame;
}
/*
在 JS 和原生中都设置弹性尺寸可能导致不确定的行为。
改变根视图的弹性模式将会导致布局的重新计算,并且在重新量出内容尺寸时会调用rootViewDidChangeIntrinsicSize方法
RCTRootView支持 4 种不同的弹性布局模式。
typedef NS_ENUM(NSInteger, RCTRootViewSizeFlexibility) {
RCTRootViewSizeFlexibilityNone = 0, 默认值
RCTRootViewSizeFlexibilityWidth,
RCTRootViewSizeFlexibilityHeight,
RCTRootViewSizeFlexibilityWidthAndHeight,
};
React Native 布局是通过一个特殊的线程进行计算,而原生 UI 视图是通过主线程更新。这可能导致短暂的原生端和 React Native 端的不一致。
*/
<6>info.plist中加
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<7>运行应用
项目根目录下
npm start
启动开发服务器(即 Packager,它负责实时监测 js 文件的变动并实时打包,输出给客户端运行)
react-native run-ios
运行应用