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

Posted xj_love

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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传值


然后再JS里面调用如:this.props.clickID 来获取对应参数

3.3RN调用原生方法

SRRNCommonManager类(继承NSObject),并实现导入以下代码
1.#import <React/RCTBridgeModule.h>
2.协议 <RCTBridgeModule>
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 <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>

3.协议<RCTBridgeModule>
4.原生代码实现

RCT_EXPORT_MODULE();

- (NSArray<NSString *> *)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项目应用总结+踩坑集锦的主要内容,如果未能解决你的问题,请参考以下文章

FlatList踩坑之onEndReached

react-native持续踩坑总结

集成RN到现有的产品项目中的踩坑记

Xamarin.Forms踩坑集锦(持续更新)

spark初探踩坑集锦

最全 Prometheus 踩坑集锦