react navite原生事件监听、全局事件通知

在 React Native(RN)里,"原生事件监听"和"全局事件通知"通常分两类:

  1. Native → JS 事件通知(原生主动通知 RN)
  2. JS 全局事件总线(RN 内部模块间通信)

下面分别讲。


一、Native → JS 原生事件监听

典型场景:

  • Android 原生收到推送
  • 蓝牙状态变化
  • GPS 定位变化
  • 登录状态变化
  • 支付结果回调
  • 原生 SDK 回调

流程:

yaml 复制代码
Android/iOS
    |
    | sendEvent
    ↓
React Native Bridge / JSI
    |
    ↓
JavaScript EventEmitter
    |
    ↓
addListener()

Android 示例

1. 原生 Module 发送事件

Java:

scala 复制代码
public class MyNativeModule extends ReactContextBaseJavaModule {

    private ReactApplicationContext context;

    public MyNativeModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.context = reactContext;
    }


    @Override
    public String getName() {
        return "MyNativeModule";
    }


    public void sendLoginEvent(String token) {

        context
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
        .emit(
            "LoginSuccess",
            token
        );
    }
}

这里:

scss 复制代码
emit(
 "LoginSuccess",
 token
)

就是发送 RN 事件。


2. JS 监听

javascript 复制代码
import {
 DeviceEventEmitter
} from 'react-native';


useEffect(()=>{


 const listener =
 DeviceEventEmitter.addListener(
   'LoginSuccess',
   (token)=>{

      console.log(
        "登录成功",
        token
      );

   }
 );


 return ()=>{

    listener.remove();

 }


},[])

效果:

makefile 复制代码
Android:
emit("LoginSuccess","abc")


JS:

收到

token="abc"

iOS 示例

Objective-C:

objectivec 复制代码
#import <React/RCTEventEmitter.h>


@interface MyEventEmitter : RCTEventEmitter

@end



@implementation MyEventEmitter


RCT_EXPORT_MODULE();



- (NSArray<NSString *> *)supportedEvents
{
    return @[
        @"LoginSuccess"
    ];
}



- (void)sendLogin:(NSString *)token
{

 [self sendEventWithName:
        @"LoginSuccess"
        body:token];

}


@end

JS:

ini 复制代码
import {
 NativeEventEmitter,
 NativeModules
} from 'react-native';


const emitter =
new NativeEventEmitter(
 NativeModules.MyEventEmitter
);


const sub =
emitter.addListener(
 "LoginSuccess",
 token=>{
    console.log(token)
 }
);


sub.remove();

二、RN 内部全局事件通知

比如:

css 复制代码
页面A登录

        ↓

通知

        ↓

页面B刷新用户信息

不需要 Native。

常用方案:


方案1:EventEmitter 全局事件总线

安装:

复制代码
npm install eventemitter3

创建:

bash 复制代码
src/utils/EventBus.js
arduino 复制代码
import EventEmitter from 'eventemitter3';


export default new EventEmitter();

发送:

python 复制代码
import EventBus from './EventBus';


EventBus.emit(
 "USER_LOGIN",
 {
   id:100
 }
);

监听:

javascript 复制代码
import EventBus from './EventBus';


useEffect(()=>{


 const handler=(user)=>{

    console.log(user)

 }


 EventBus.on(
   "USER_LOGIN",
   handler
 );


 return ()=>{

   EventBus.off(
     "USER_LOGIN",
     handler
   );

 }


},[])

结构:

scss 复制代码
        EventBus

 A页面
 emit()

       |
       |
       ↓

 USER_LOGIN


       |
       |
       ↓


 B页面
 on()

三、React Native 推荐方案

现在 RN 项目一般不会大量使用 EventBus。

更推荐:

场景 推荐
组件状态共享 Zustand
复杂业务状态 Redux Toolkit
服务器数据 React Query
Native通知JS NativeEventEmitter
简单跨页面通知 EventEmitter

例如登录:

不推荐:

csharp 复制代码
LoginPage

EventBus.emit("LOGIN")

HomePage

EventBus.on("LOGIN")

推荐:

csharp 复制代码
             Zustand

login()
  |
  |
 user={name:"张三"}

  |
  |
所有组件自动更新

四、RN 新架构 Fabric / TurboModule 下

你之前问过 Fabric,这里补充:

旧架构:

arduino 复制代码
Native
 |
Bridge
 |
JS

事件:

scss 复制代码
emit()
 ↓
Bridge Queue
 ↓
JS EventEmitter

新架构:

yaml 复制代码
Native Module
       |
       |
     JSI
       |
       |
 JavaScript Runtime

通信更直接。

但是:

  • DeviceEventEmitter
  • NativeEventEmitter

仍然大量存在。

TurboModule 推荐:

php 复制代码
interface Spec extends TurboModule {

 addListener(
   eventName:string
 ):void;


 removeListeners(
   count:number
 ):void;

}

然后:

arduino 复制代码
NativeModule.addListener(
 "EVENT"
)

五、实际项目架构建议

例如 App:

markdown 复制代码
                 Native


 推送SDK
 蓝牙SDK
 支付SDK
 登录SDK

       |
       |
       ↓


 NativeEventEmitter


       |
       |
       ↓


 event adapter


       |
       |
       ↓


 Zustand / Redux


       |
       |
       ↓


 React Components

不要让页面直接监听 Native。

推荐:

复制代码
Native
 ↓
Service层
 ↓
Store
 ↓
页面

这样维护性最好。


如果你是想实现类似微信桌面端扫码登录那种"原生扫码成功通知 RN 页面刷新" ,一般就是 NativeEventEmitter + 状态管理(Store) 这一套。你前面问过微信扫码登录,这个场景正好对应。

相关推荐
H_Lisa7 小时前
我用 Express 写了个 MCP,Claude 直接调用我的 API 了
前端
IT_陈寒8 小时前
React的useEffect依赖数组把我坑惨了
前端·人工智能·后端
兰亭妙微UI设计公司9 小时前
兰亭妙微ui设计公司分享:B端组件命名如何支持团队协作
前端·javascript·vue.js
云和数据.ChenGuang9 小时前
光哥说Python 异常深度解析:从异常模型到工程化实践
java·前端·人工智能·python·langchain
小大宇9 小时前
Vue知识点-ElementPlus-03提示框+询问+通知
前端·javascript·vue.js
步行cgn10 小时前
Axios 请求成功但页面不显示:两个前端错误的分析与修正
前端
时间的情敌11 小时前
WebGIS + OpenLayers + GeoServer + PostGIS #量算 #点聚合
前端·geoserver·openlayers
不可能片场12 小时前
Electron 发布 cookie 库先查明文再写解密
前端·electron
郭小李12 小时前
springmvc 拦截器
java·开发语言·前端
web打印社区12 小时前
Chrome-kiosk-printing能上生产吗
开发语言·前端·javascript·chrome·websocket