Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Native DeviceEventEmitter/NativeEventEmitter使用以及原生拓展 #5

Open
1uokun opened this issue Apr 22, 2020 · 0 comments
Labels
blog 日常开发笔记

Comments

@1uokun
Copy link
Member

1uokun commented Apr 22, 2020

DeviceEventEmitter for android

JavaScript端

import { DeviceEventEmitter } from 'react-native';

// addListener
let context = null;
DeviceEventEmitter.addListener('YOUR_EVENTNAME', (msg) => {
   console.log(msg);
   console.log(this); // null
 },context);

// emit
DeviceEventEmitter.emit('YOUR_EVENTNAME',msg);

//removeAllListeners
DeviceEventEmitter.removeAllListeners('YOUR_EVENTNAME');

Android拓展实现

import com.facebook.react.modules.core.DeviceEventManagerModule;

getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
            .emit("YOUR_EVENTNAME", "msg");

最初DeviceEventEmitter是用于发送原生的BackPress点击事件,
所以Android通过DeviceEventEmitter.emit()Android RCTDeviceEventEmitter emit都可以触发执行。

NativeEventEmitter for iOS

JavaScript端

import { NativeModules,NativeEventEmitter } from 'react-native';
const { IOSNativeModule } = NativeModules;

this._eventEmitter = new NativeEventEmitter(IOSNativeModule);
this._eventEmitter.addListener("IOS_EVENTNAME",(msg) => {
   console.log(msg)
})

this._eventEmitter.removeAllListeners("IOS_EVENTNAME")

iOS拓展实现

.h文件需要修改为继承RCTEventEmitter

#import <React/RCTBridgeModule.h>
+ #import <React/RCTEventEmitter.h>

- @interface AwesomeModule : NSObject <RCTBridgeModule>
+ @interface AwesomeModule : RCTEventEmitter <RCTBridgeModule>

@end

.m文件

// 注册事件名称
- (NSArray<NSString *> *)supportedEvents
{
  return @[@"EventReminder"];
}

// 派送指定名称的事件
[self sendEventWithName:@"EventReminder" body:@{@"name": data}];

Issue

  • Android可能存在的问题:
    当不同NativeModule内emit()相同的eventName时,android会存在监听事件都会被执行的问题。
    所以在做原生拓展时,定义的eventName最好有独特的标识字符以防止其他NativeModule借用RCTDeviceEventEmitter类时定义的eventName和您的重名。
  • iOS可能存在的问题:
    首先,iOS不存在上述重名问题。
    其次,必须使用new NativeEventEmitter()来注册监听事件eventName。但是一旦注册成功,那么DeviceEventEmitter也能监听到该eventName事件。如以下代码所示:
    this._eventEmitter = new NativeEventEmitter(IOSNativeModule);
    this._eventEmitter.addListener("IOS_EVENTNAME",(msg) => {
       console.log(msg)
    })
    DeviceEventEmitter.addListener("IOS_EVENTNAME",(reminder) => {
       console.log(reminder.name); //“IOS_EVENTNAME”一旦被注册成功,这里也会被执行
    })
    好处是下次监听时不需要再实例化一次NativeEventEmitter ,坏处是容易混淆监听事件。
    所以建议仅针对iOS原生发送给JS的事件命名时添加IOS_标识。

Reference

@1uokun 1uokun added the blog 日常开发笔记 label Apr 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blog 日常开发笔记
Projects
None yet
Development

No branches or pull requests

1 participant