React-Native实践总结

React-Native分析

RN的优点:

  1. 页面热更新
  2. RN页面不需要移动端发版本
  3. 纯web思维,开发速度快,且体验优于h5,
  4. 第三方插件也比较多
  5. 部分功能代码实现一端开发多端共用(“Learn once,write anywhere”?)

RN的缺点:

  1. 下载包体变大,多了一个RN的sdk
  2. 调试相对麻烦
  3. 兼容性问题放大了
  4. 开发要求高了,js、native都需要了解

数据的传递(交互):

React-Native 数据交互

RN 拥有画UI的跨平台能力,主要是加入Virtual DOM编程模型,该方法一方面可以照顾到JS开发者在html DOM的部分传承, 让JS 开发者可以用类似DOM编程模型就可以开发原生APP , 另一方面则可以让Virtual DOM适配实现到各个平台,实现跨平台的能力

JS与Native模块之间通信,主要有三种方法:

  1. 使用回调函数Callback,它提供了一个函数来把返回值传回给JavaScript。
  2. 使用Promise来实现。
  3. 原生模块向JavaScript发送事件。

JS调用Native

js调用原生功能模块需要用到RN模块NativeModules并获取到native的指定module

import { NativeModules } from 'react-native'
var jsToNativeEmitter = NativeModules.KJSToNativeEmitter

js调用原生组件需要用到RN模块requireNativeComponent并获取到native的指定组件

import { requireNativeComponent } from 'react-native'
let RTCView = requireNativeComponent('RNCustomView', RNCustomView, {})

功能模块和组件的需要在Native中先声明定义.如下:

JS调用Native之iOS

RCTBridgeModule桥接模块,管理JS和OC交互, 一个“原生模块”就是一个实现了“RCTBridgeModule”协议的 Objective-C 类,很重要!!

类名:RCT_EXPORT_MODULE 标记宏

常量:constantsToExport. 导出常量给js

方法:RCT_EXPORT_METHOD 导出方法
...等等

模块的定义:

RCT_EXPORT_METHOD:原生方法导出,生成对应js方法,供JS调用.很重要!一般通过这个宏定义的路由.但是回调不带有属性传递!!!

把callBack传回给 JavaScript

typedef void (^RCTResponseSenderBlock)(NSArray *response);
typedef void (^RCTResponseErrorBlock)(NSError *error);

把Promise对象传回给 JavaScript

typedef void (^RCTPromiseResolveBlock)(id result);
typedef void (^RCTPromiseRejectBlock)(NSString *code, NSString *message, NSError *error);
封装组件的定义:

继承RCTViewManager
实现view的定义
属性:RCT_EXPORT_VIEW_PROPERTY。通过该宏完成属性的映射和导出

自定义属性:RCT_CUSTOM_VIEW_PROPERTY

事件导出:RCTBubblingEventBlock 通过属性实现RCT_EXPORT_VIEW_PROPERTY(onXXX, RCTBubblingEventBlock)

JS调用Native之Android

类名:需要实现方法public String getName()
常量: 需要实现public Map<String, Object> getConstants()

方法:@ReactMethod

模块的定义:

需要在createNativeModules中声明

public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Arrays.<NativeModule>asList(new KJSToNativeEmitter(reactContext));
    }
封装组件的定义:

需要实现createViewInstance(ThemedReactContext reactContext)
需要在createViewManagers中声明
需要继承ViewManagerBaseViewManagerSimpleViewManager
属性:@ReactProp@ReactPropGroup

@Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
//        return Collections.emptyList();
        return Arrays.<ViewManager>asList(new RNCustomViewManager());
    }

Native调用JS

native调用原生分为两种:被动和主动
被动:通过js调native返回callBack或Promise的方式
主动:通过RCTDeviceEventEmitter强制发起事件

js调用native需要用到RN中的NativeEventEmitterNativeModules模块,并获取到原生指定的模块

import { NativeEventEmitter, NativeModules } from 'react-native'
var nativeBridge = NativeModules.KNativeToJSEmitter //未定义module 就是你的类名
const NativeModule = new NativeEventEmitter(nativeBridge)

componentDidMount(){  
  this.listener = RCTDeviceEventEmitter.addListener('通知名称',(value)=>{  
    // 接受到通知后的处理  
  })
}  
  
componentWillUnmount(){  
  // 移除 一定要写  
  this.listener.remove()
}

Native调用JS之iOS:

继承RCTEventEmitter,并实现RCTBridgeModule协议
RCT_EXPORT_MODULE(xxx);指定module名

///指定module名,不传入就是类名
RCT_EXPORT_MODULE();
#pragma mark - 重写父类方法
///返回所有原生端发往js端的消息名字
- (NSArray<NSString *> *)supportedEvents
{
    return EventEmitterNames;
}

    //发起事件
    [self sendEventWithName:emitterName body:object];

Native调用JS之Android:

需要获取到当前的ReactContext,并通过它来发事件

    //发消息
    private static final String KEventName = "KNativeToJSEmitter";

    public void sendEvent(ReactContext reactContext,
                           @Nullable WritableMap params) {
        if (reactContext==null) {
            Log.i(TAG, "reactContext==null");
        }else{
            reactContext
                    .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                    .emit(KEventName, params);
        }
    }

总结

对于大多数app开发者来说,ReactNative没有想象中的难,但也有不少坑.个人觉得RN不宜覆盖整个app,适用于app内某些活动页, 使用时尽量少用原生层次自定义的组件,可以用js来封装基础组件!这样子在版本迭代的时候会轻松点.

js调用native统一入口,定个规则

RCT_EXPORT_METHOD(sendMsg:(NSInteger)msgType
                  message:(NSString *)msg) 
                 resolver:(RCTPromiseResolveBlock)resolver
                 rejecter:(RCTPromiseRejectBlock)reject){   
}

@ReactMethod
  public void sendMsg(
      int msgType,
      String msg,
      Promise promise)

msgType:事件类型
msg:传递的具体消息 类似路由

附:

React-Native官方安装教程:https://reactnative.cn/docs/getting-started.html

@ReactMethod注明的方法中 native 与 js类型之间关系
js与iOS:

string (NSString)
number (NSInteger, float, double, CGFloat, NSNumber)
boolean (BOOL, NSNumber)
array (NSArray) 可包含本列表中任意类型
object (NSDictionary) 可包含 string 类型的键和本列表中任意类型的值
function (RCTResponseSenderBlock)

Android与js:

Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
```![![5bc6abb6e4b0534c9c063dc2.png](https://upload-images.jianshu.io/upload_images/2906485-650c96fcb9b89fd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
](https://upload-images.jianshu.io/upload_images/2906485-59f348c9fb8a682a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354

推荐阅读更多精彩内容