React Native简介:
React-Native 是由Facebook出品的一款可以使用JavaScript来编写原生app的框架,官方说明是:A framework for building native app with React(一个使用React来编写原生app的框架),然而这个React也是由该公司出品的一款可以用来编写用户界面的JS库。二者的出现,以其强大的功能和便捷的使用方式迅速被广大开发者使用,并在各大平台的应用研发中占据了自己的一席之地。
集成
本文主要讲解的是在现有项目中如何集成React-Native框架,其他操作请自行查阅官网。
OK, let's do this...
准备工作:
- 搭建基本的React-Native开发环境,请参考这里。
- 安装cocoapods,如果没有请参考官网。之后的操作是建立在已安装cocoapods,并且项目中已有podfile文件的情况下。
- 准备一个好用的文本编译器,用于编译.json文件和.js文件。
开始集成:
首先需要调整一下目录结构,方便管理,虽然官网推荐的是新建文件夹,并建ios子目录,然后将项目放入。但这并不是我们想干的,我们还是习惯根目录下面是原生的东西。我的建议是,在项目根目录中创建一个文件夹,自定义名称,用于放置所有与React-Native相关文件和文件夹。
然后,打开该文件夹,在文件夹中创建一个package.json的文件,该文件将作为React-Native的配置文件存在。并在文件中加入以下内容
{
"name": "YouProjectName",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "16.0.0-alpha.12",
"react-native": "0.47.1"
}
}
注:请将name后面替换为自己的项目的名称,另外,react和React-Native版本请查阅官网确定是最新版本。
创建该文件最快的方法是,打开终端,cd到你创建的文件夹下,并输入
$touch package.json
再使用文本编译器来编辑即可。
$ npm install
等待终端执行完毕后,该文件夹下会多出一个node_modules的文件夹,里面是所有React 和React-Native相关模块。
cocoapods终于要上场了,安装依赖库的之前必须要使用node_modules下的相关配置文件,所有要先安装模块,导入库。
打开podfile,并在其中加入如下代码:
pod 'React', :path => './YourReactNativeFolder/node_modules/react-native', :subspecs => [
'Core', #核心库
'BatchedBridge', #RN版本高于0.45之后必须导入
'DevSupport', # 如果RN版本 >= 0.43,则需要加入此行才能开启开发者菜单
'ART',
'RCTActionSheet',
'RCTAdSupport',
'RCTAnimation',
'RCTCameraRoll',
'RCTGeolocation',
'RCTImage',
'RCTNetwork',
'RCTPushNotification',
'RCTSettings',
'RCTText',
'RCTVibration',
'RCTWebSocket', # 这个模块是用于调试功能的
'RCTLinkingIOS'
]
# 如果你的RN版本 >= 0.42.0,则加入下面这行
pod 'Yoga', :path => './YourReactNativeFolder/node_modules/react-native/ReactCommon/yoga'
保存之后,执行pod install命令即可。
成功之后,回来先编译一下程序,如没有报错,说明集成成功。
页面嵌入
集成之后,当然是怎么在现有项目中使用了。
首先需要创建React-Native框架的iOS入口文件,即index.ios.js。
据官方介绍该文件是必须创建的,作为入口存在,可以很简单,但必须有。
创建方法推荐在使用touch命令,即在终端进入package.json所在文件夹,输入命令
$ touch index.ios.js
之后用文本编译器打开,写入以下代码作为测试使用:
'use strict';
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
//{'\n'}换行符
export default class ReactPage extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
这就是所谓的{'\n'}
React Native
</Text>
<Text style={styles.instructions}>
模拟器中cmd+R刷新页面,cmd+D调出调试菜单
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F2F2F2',
},
welcome: {
fontSize: 24,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('YourProjectName', () => ReactPage);
注:请将最后的YourProjectName替换成你项目的名称。
然后就是在项目代码中调用React-Native页面了,这里需要做的就是先找到需要调用React-Native页面的位置,在页面中引入头文件:
#import <React/RCTRootView.h>
然后在事件处理方法中添加如下代码:
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"AiFlow" initialProperties:nil launchOptions:nil];
rootView.backgroundColor = [UIColor colorWithHexString:@"#F2F2F2"];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self presentViewController:vc animated:YES completion:nil];
完成后,即可点击运行,以模拟器打开。
但,如果现在触发该事件,则无法展示页面,因为React-Native的服务端并未启动,因此在触发事件之前,需要先打开终端,进入package.json文件所在目录,并执行:
$ npm start
等待服务器启动后,便可触发该事件,等待页面加载即可。
好了,至此,集成加运行调试结束,可以愉快地修改index.ios.js文件里的代码玩耍吧。
坑
是的,坑就是坑,永远在那里,不管你踩不踩。
1. 很多同学纠结于目录结构,生怕如果不按照官网的步骤进行就无法集成成功,其实不然,目录是死的,人是活的,只要将需要设置路径的地方设置正确就不会有影响,比如podfile中的path。路径的写法中 ./ 代表的是该文件所在目录,../ 代表的是该文件所在上级目录,因此官网的写法是 ../,因为按照他所创建的文件结构,node_modules文件夹就是在podfile的上级目录。如果pod install命令报错,先检查cocoapods的版本,需要1.2.0以上版本,再检查path路径是否写的正确。
2. 巨坑:关于podfile中React库的subspecs该引入哪些组件的问题。先说一下我集成时遇到的情况,我在按照官网的集成方法做完之后,信心满满的点了一下运行,结果您猜怎么着,Xcode编译报错了。。。是的,不是React-Native报错,是Xcode报错,错误类型是Undefined symbols 错误指引告诉我说要添加类库libReact.a。好吧,我就加咯,加了之后编译,仍然报错。我就奇怪了,于是开始查资料,但貌似根本没有类似于我这样的情况出现。怎么办呢,整整一天时间,我都在研究到底哪里出了问题,直到看到了 这篇文章 ,豁然开朗。。。
所谓的未找到libReact.a的错误仅仅是因为我少导入了一个组件,这个组件的名字叫 BatchedBridge,该组件是React-Native0.45版本以后需要添加的依赖库,但官 网的代码中的代码是酱紫的:
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'DevSupport', # 如果RN版本 >= 0.43,则需要加入此行才能开启开发者菜单
'RCTText',
'RCTNetwork',
'RCTWebSocket', # 这个模块是用于调试功能的
# 在这里继续添加你所需要的模块
]
所以解决办法就是多引入一个'BatchedBridge'。呵呵哒,一天的时间就这么白白搭进去了,所以同学们注意了,只要出现跟libReact.a相关的错误,一定不是因为未找到该库,
而是缺少了上述依赖组件。
3. 出现与http请求相关的错误时,需在info.plist文件中设置App Transport Security允许http请求,并设置localhost字段,即在info.plist文件中加入:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
OK就这些。