RN项目应用总结+踩坑集锦

前段时间粗糙的研究了下React Native,写了两篇集成文章(幸好写了文章,时间长了有些东西还真忘了集成一,集成二),后面断断续续研究了下,因为没有实际项目运用,感觉学习的不连贯。这两个星期用RN技术复刻一个旧的项目,方才让学到的东西有了使用,两星期就正式上线了。不过这其中可以说是一步一坑,不过最终都解决了。因为时间紧,有些没来得错误没来得及截图,不过这里会记录一些关键的坑和要点,希望对大家有所帮助。

一、项目准备

1.编译软件推荐 —> Visual Studio Code,一开始尝试用Sublime(写H5的时候一直用的),但是发现好别扭,用VS还是挺顺手,推荐

2.在现有项目集成RN,可以参考我的集成文章 –集成一,集成二)

二、打包上线

2.1 让项目本地运行

真机测试的时候我们都用的本地局域网路径,启动RN服务,如:
在这里插入图片描述
但是上线的时候,我们要打包,所以不能这样访问,要做以下操作:
1.再你的RN文件夹下新建bundle文件夹
2.终端cd到RN目录
3.执行命令 react-native bundle --entry-file ./App.js --bundle-output ./bundle/index.ios.jsbundle --platform ios --assets-dest ./bundle --dev
注*:.App.js 你的主JS名称,自行修改
4.build下文件全部拖到Xcode工程
5.每次JS有修改,都要重新执行命令
然后如下访问:
在这里插入图片描述

2.2 热更新

1.快速入门-准备工作
2.快速入门-添加热更新功能
3.快速入门-发布应用
4.常见问题

三、要点集锦

3.1解决版本升级,或第三方,Navigator不可用问题

1、打开终端,cd 当前RN目录
2、输入并运行 npm install react-native-deprecated-custom-components --save
3、在使用到Navigator组件时换成 :NavigationExperimental.Navigator即可(如果没报错,这句可以忽略)

3.2原生给RN传值

RN项目应用总结+踩坑集锦_第1张图片
然后再JS里面调用如:this.props.clickID 来获取对应参数

3.3RN调用原生方法

SRRNCommonManager类(继承NSObject),并实现导入以下代码
1.#import
2.协议
3.原生代码实现

//为了实现RCTBridgeModule协议,需要包含RCT_EXPORT_MODULE()宏。
//这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。
//如果不指定,默认就会使用这个Objective-C类的名字。
RCT_EXPORT_MODULE()

//js跳到原生-调到原生到访确认单
//通过RCT_EXPORT_METHOD()宏声明要给Javascript导出的方法,否则React Native不会导出任何方法。
//方法名,参数可以自定义
RCT_EXPORT_METHOD(pushVisitConfirmation:(NSString *)message type:(NSString *)type)
{
}

4.JS代码实现

//导入
import { 
  NativeModules
} from 'react-native';

//声明一个参数,格式如下
var SRRNCommonManager = NativeModules.SRRNCommonManager; 

//调用
 SRRNCommonManager.pushVisitConfirmation(
                                    "参数message",
                                    "参数type"
                                    );

3.4原生调用JS(严格说是原生给JS主动传值)

1.写一个继承RCTEventEmitter的类SRActionToJS
2.导入

#import 
#import 

3.协议
4.原生代码实现

RCT_EXPORT_MODULE();

- (NSArray *)supportedEvents
{
    return @[@"EventReminder"];  //必须实现,可以注册多个  原生给JS发送数据
}
//固定格式
- (void)startObserving
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(emitEventInternal:)
                                                 name:@"event-emitted"
                                               object:nil];
}
//固定格式
- (void)stopObserving
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
//通知实现,给JS传值
- (void)emitEventInternal:(NSNotification *)notification
{
    [self sendEventWithName:@"EventReminder" body:@{@"imageData":notification.object}];
}

//暴露给外部的方法,这里我需要的是base64的图片
+ (void)actionToJSEventReminderReceived:(NSString *)imageData  //触发方法  用类方法,对象方法,alloc可能会报错
{
   [[NSNotificationCenter defaultCenter] postNotificationName:@"event-emitted" object:imageData];
}

5.JS代码实现

//导入
import {
    NativeModules,
    DeviceEventEmitter
} from 'react-native';
//声明
var nativeBridge = NativeModules.SRActionToJS;
const SRActionToJSManagerEmitter = new NativeEventEmitter(nativeBridge);
//监听+实现
componentDidMount() { //声明周期,JS加载完成
        if (!this.subscription) {
            this.subscription = SRActionToJSManagerEmitter.addListener('EventReminder', (result) => {
                try {
                     result.imageData  //实现,拿到原生的传值
                 } catch (error) {
                 }
              });
}

3.5NavigatorIOS要点,也可以使用第三方封装好的导航,这里时间原因,就用了这个

1.shadowHidden: true 隐藏导航栏,如果实现不了,尝试调换代码顺序,对,就是这么神奇
2.给下个页面传值

passProps: {
                    kHeight: this.props.screenHeight,
                    kisIos11: this.props.isIos11,
                }
//下个页面直接调用:tihs.props.kHeight就可以

3.6监听触发时机

RN里面也有类似于原生的监听方法。有个需求是当前值发生变化,要刷新上个页面的数据,这时候用到通知。但是实现的通知方法,只走打印,不走刷新数据的方法。研究了下,可能是发送通知的时机问题,换了下发送的时机,就能正常运行。

//A页面注册监听,'changeData' 触发参数,param收到的传值
componentDidMount() {
        this.refreshData(true);
        this.subscription = DeviceEventEmitter.addListener('changeData',(param) => {
            this.refreshData(true,true)  //自行处理事件方法
        })
    }
componentWillUnmount() {  
        if (this.subscription) {  //注销监听
            this.subscription.remove()
            this.subscription = null
        }
    }

//B页面发送通知,如数据改变,需要通知A页面刷新,不能像原生那样直接发通知,我的处理是:

componentWillUnmount() { //页面将要注销,另外,注册了监听,在当前页面要注销
        if(this.successLoad){  //用一个全局参数记录是否需要发送通知
            DeviceEventEmitter.emit('changeData','参数') //发送监听事件
        }
        if (this.subscription) { //注销监听
            this.subscription.remove()
            this.subscription = null
        }
    }

欢迎大家入群交流学习,高级iOS开发交流群:855808379

RN项目应用总结+踩坑集锦_第2张图片

你可能感兴趣的:(iOS+React,Native混合开发,移动端+大前端+后台学习整合)