RN环境搭建及与原生交互
🇨🇳中文介绍
RN
全称React Native
,是Facebook
公司推出的一款能够跨平台开发的框架,其能够使用js
来达到安卓端
和iOS端
共用一套代码开发的目的。React Native
的核心设计理念是:即拥有React
的开发效率,又能拥有Native
的体验。
版本支持
iOS目前支持7.0以上的版本,安卓目前支持4.1以上的版本
开发环境配置
环境要求
安装Homebrew
在终端中输入下面的命令,执行的速度可能比较慢,请耐心等待其执行完成
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
在终端中输入下面的命令验证是否安装成功
brew -v
安装npm和Node.js
安装watchMan
该插件用于监控bug文件和文件变化,并且可以触发指定的操作,在终端中输入下面的命令就可以了
brew install watchman
安装Flow
flow是一个JavaScript的静态类型检查器,建议安装它,以方便找出代码中可能存在的类型错误,在终端输入下面的代码,如果提示command not found ,请加上sudo获得最高权限。
brew install flow
React Native安装
在终端输入
npm install -g react-native-cli
到这里React Native的环境就已经全部配置好了
创建React Native 项目
在终端中输入下面命令
react-native init 项目名称
如果速度较慢,可以将npm仓库源替换为国内镜像:
npm config set registry https://registry.npm.taobao.org
npm config set disturl https://npm.taobao.org/dist
默认生成了三个文件夹,android和iOS为两个平台的原生项目,index.android.js和index.ios.js为android和iOS平台下的两个空壳应用文件,我们的代码一般就写在这两个文件内,客户端那边不用重新run就可以看到效果,node_modules文件夹主要是存放框架资源。
对index.ios.js文件的编写软件以及提示插件的安装
我们采用的是WebStorm来对js文件来进行编写,由于直接编写并没有代码提示,所以这里要安装一个插件,下载地址,下载完成后file -> import settings -> ReactNative.jar ,完成之后就可以像Xcode那样能够自动提示了.
在现有项目中集成RN
官方推荐的方式是利用CocoaPods
把React Native
组件植入到iOS应用中有如下几个主要步骤:
1.首先当然要了解你要植入的React Native
组件
2.创建一个Podfile
,在其中以subspec
的形式填写所有你要植入的React Native
的组件。
3.创建js
文件,编写React Native
组件的js代码
4.添加一个事件处理函数,用于创建一个RCTRootView
。这个RCTRootView
正是用来承载你的React Native 组件的,而且它必须对应你在index.ios.js
中使用AppRegistry
注册的模块名字。
5.启动React Native
的Packager
服务,运行应用
6.根据需要添加更多的React Native 组件
准备工作
首先确定你的Mac里有没有安装下面的两个环境:
1.react-native
2.CocoaPods
直接在终端敲下面的两个命令,就能看看你有没有装咯
1.react-native -v
2.pod --version
从无到有
如果你是一个小白,那么我们就从头开始吧
1.首先打开我们的Xcode创建一个项目,用终端cd到你刚创建好的项目文件夹中
2.用终端执行pod init 然后再执行 pod install
3.在你的项目文件夹里创建一个文件夹来管理RN,习惯用命令了,直接终端
mkdir RNUtil
cd RNUtil
4.创建一个package.json的文件
touch package.json
5.在这个文件夹下执行npm install
6.等安装成功后,创建index.ios.js文件,我们就可以开始我们的混编之旅了
touch index.ios.js
Podfile
# Uncomment the next line to define a global platform for your project
platform :ios, ‘8.0’
inhibit_all_warnings!
target 'RNBridgeSwift' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for RNBridgeSwift
# react_path 是你react-native文件夹路径。
react_path = './RNUtil/node_modules/react-native'
yoga_path = File.join(react_path, 'ReactCommon/yoga')
pod 'React', :path => react_path, :subspecs => [
'Core',
'RCTText',
'RCTImage',
'RCTWebSocket', # needed for debugging
'RCTNetwork'
]
pod 'Yoga', :path => yoga_path
end
Package.json
{
"name": "RNBridgeSwift",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "15.4.2",
"react-native": "0.42.3"
}
}
Demo
环境搭建好了后,我们就开始搞个小demo玩玩
首先在准备当做原生的页面的Controller里导入React
import React
写点啥好呢,就随便写个按钮加俩Label可以实现页面跳转和传值吧
重点来了哦,在按钮的点击方法里写上下面的代码
let localJSPath = URL.init(string:"http://localhost:8081/index.ios.bundle?platform=ios")
let params:[String:Array<Dictionary<String, String>>] = [
"scores" : [
["name":"Alex","value":"42"],
["name":"Joel","value":"10"],
]
]
let rootView : RCTRootView = RCTRootView(bundleURL: localJSPath, moduleName: "RNTestViewModule", initialProperties: params, launchOptions: nil)
对了,还要创建一个承载js页面的Controller
在这个Controller的viewWillAppear方法里注册两个通知:
NotificationCenter.default.addObserver(self, selector: #selector(RNManagerViewController.backPreviousVC(_:)), name: NSNotification.Name.init(rawValue: "NotificatioinBack"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(RNManagerViewController.backPreviousVC(_:)), name: NSNotification.Name.init(rawValue: "NotificatioinNext"), object: nil)
创建一个类目来诠释通知:
extension RNManagerViewController {
func backPreviousVC(_ notification: Notification) {
print("current Thread %@",Thread.current)
DispatchQueue.main.async {
if (self.backBlock != nil) {
self.backBlock!(notification.object ?? "");
}
if let navigationVC: UINavigationController = self.navigationController, navigationVC.viewControllers.count > 1 {
navigationVC.popViewController(animated: true)
} else {
self.dismiss(animated: true, completion: nil)
}
}
}
func nextHandle(_ notification: Notification) {
print("current Thread %@",Thread.current)
DispatchQueue.main.async {
if (self.backBlock != nil) {
self.backBlock!(notification.object ?? "");
}
}
}
}
重点来了,引入OC的桥接文件,使RN可以实现OC的方法。
RCT_EXPORT_MODULE(swift);
RCT_EXPORT_METHOD(transportMessage:(id)message){
NSLog(@"transportMessage:\n %@",message);
if ([message isKindOfClass:[NSDictionary class]]) {
NSString *method = [message objectForKey:@"method"];
BOOL isNext = method ? ([method isEqualToString:@"push"] || [method isEqualToString:@"present"]) : NO ;
if (isNext) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificatioinNext" object:message userInfo:nil];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificatioinBack" object:message userInfo:nil];
}
}
}
//RN传参数调用原生OC,并且返回数据给RN 通过CallBack
RCT_EXPORT_METHOD(RNInvokeOCCallBack:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback){
NSLog(@"接收到RN传过来的数据为:%@",dictionary);
NSArray *events = @[
@{
@"name" : @"王垒",
@"value": @"111"
},
@{
@"name" : @"King",
@"value": @"99"
}
];
callback(@[[NSNull null], events]);
}
效果图如下:
RNBridgeSwift.gif
总结
如果你有需要请点下面的按钮前往Clone。
Clone
git clone https://github.com/KingComeFromChina/RNBridgeSwift.git