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 getConstants()

方法:@ReactMethod

模块的定义:

需要在createNativeModules中声明

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

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

@Override
    public List createViewManagers(ReactApplicationContext reactContext) {
//        return Collections.emptyList();
        return Arrays.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 *)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)

你可能感兴趣的:(React-Native实践总结)