React-Native實踐總結

React-Native分析

RN的優(yōu)點:

  1. 頁面熱更新
  2. RN頁面不需要移動端發(fā)版本
  3. 純web思維,開發(fā)速度快,且體驗優(yōu)于h5,
  4. 第三方插件也比較多
  5. 部分功能代碼實現(xiàn)一端開發(fā)多端共用(“Learn once,write anywhere”?)

RN的缺點:

  1. 下載包體變大,多了一個RN的sdk
  2. 調試相對麻煩
  3. 兼容性問題放大了
  4. 開發(fā)要求高了,js、native都需要了解

數(shù)據(jù)的傳遞(交互):

React-Native 數(shù)據(jù)交互

RN 擁有畫UI的跨平臺能力,主要是加入Virtual DOM編程模型,該方法一方面可以照顧到JS開發(fā)者在html DOM的部分傳承, 讓JS 開發(fā)者可以用類似DOM編程模型就可以開發(fā)原生APP , 另一方面則可以讓Virtual DOM適配實現(xiàn)到各個平臺,實現(xiàn)跨平臺的能力

JS與Native模塊之間通信,主要有三種方法:

  1. 使用回調函數(shù)Callback,它提供了一個函數(shù)來把返回值傳回給JavaScript。
  2. 使用Promise來實現(xiàn)。
  3. 原生模塊向JavaScript發(fā)送事件。

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交互, 一個“原生模塊”就是一個實現(xiàn)了“RCTBridgeModule”協(xié)議的 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
實現(xiàn)view的定義
屬性:RCT_EXPORT_VIEW_PROPERTY。通過該宏完成屬性的映射和導出

自定義屬性:RCT_CUSTOM_VIEW_PROPERTY

事件導出:RCTBubblingEventBlock 通過屬性實現(xiàn)RCT_EXPORT_VIEW_PROPERTY(onXXX, RCTBubblingEventBlock)

JS調用Native之Android

類名:需要實現(xiàn)方法public String getName()
常量: 需要實現(xiàn)public Map<String, Object> getConstants()

方法:@ReactMethod

模塊的定義:

需要在createNativeModules中聲明

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

需要實現(xiàn)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強制發(fā)起事件

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,并實現(xiàn)RCTBridgeModule協(xié)議
RCT_EXPORT_MODULE(xxx);指定module名

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

    //發(fā)起事件
    [self sendEventWithName:emitterName body:object];

Native調用JS之Android:

需要獲取到當前的ReactContext,并通過它來發(fā)事件

    //發(fā)消息
    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);
        }
    }

總結

對于大多數(shù)app開發(fā)者來說,ReactNative沒有想象中的難,但也有不少坑.個人覺得RN不宜覆蓋整個app,適用于app內某些活動頁, 使用時盡量少用原生層次自定義的組件,可以用js來封裝基礎組件!這樣子在版本迭代的時候會輕松點.

js調用native統(tǒng)一入口,定個規(guī)則

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)
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容