通过 useEventBus 和 useEventCallBack 实现与原生 Android、鸿蒙、iOS 的事件交互

通过 useEventBususeEventCallBack 实现与 原生 Android、鸿蒙、iOS 的事件交互

这个问题在 H5 嵌入 Native 容器(如 WebView)的混合开发场景中非常常见。我们来一步步解释原理、机制和实现方式。


✅ 一、H5 与原生通信的基本原理

在 Hybrid App 中,H5 页面运行在 WebView 内部,要与原生(Android/iOS/HarmonyOS)交互,通常使用以下两种方式:

方式 说明
JSBridge 原生注入 JS 对象或函数到 WebView 的 window 上,H5 调用它发送消息;原生也可以主动调用 JS 函数
postMessage 更现代的方式,通过 window.postMessage 发送消息,原生监听并响应

你的项目中使用的 useEventBususeEventCallBack 很可能是基于这两种机制封装的事件总线模式


✅ 二、核心机制:JavaScript ↔ Native 双向通信

🔄 1. H5 → 原生(发送事件)

js 复制代码
// 方式一:调用原生暴露的方法(JSBridge)
window.Android?.sendMessage('eventName', data);
window.webkit.messageHandlers.iOS?.postMessage({ event: 'click', data });

// 方式二:通过统一 bridge(比如 JSBridge)
window.JSBridge?.call('openCamera', { quality: 'high' });

🔄 2. 原生 → H5(触发事件)

原生通过执行 JS 代码调用 H5 注册的回调函数:

js 复制代码
// 原生执行:
window.dispatchEvent(new CustomEvent('native_event_login_success', {
  detail: { token: 'xxx' }
}));

或者直接调用全局函数:

js 复制代码
window.onNativeLoginSuccess && window.onNativeLoginSuccess(res);

✅ 三、结合你的代码分析

ts 复制代码
import useEventBus from '@/hooks/useEventBus';
import { NATIVE_EVENT, useEventCallBack } from './hooks/useEventCallBack';

我们可以推测这两个 Hook 的作用是:

Hook 功能
useEventCallBack 监听来自原生的事件(如登录成功、返回键点击等)
useEventBus 主动向原生发送事件(如打开相机、跳转页面)

✅ 四、具体实现示例

✅ 1. 定义原生事件常量

ts 复制代码
// constants.ts
export const NATIVE_EVENT = {
  LOGIN_SUCCESS: 'login_success',
  PAY_RESULT: 'pay_result',
  BACK_BUTTON: 'back_button',
  NETWORK_CHANGE: 'network_change',
} as const;

✅ 2. useEventCallBack:监听原生事件

ts 复制代码
// hooks/useEventCallBack.ts
import { useEffect } from 'react';

// 模拟原生事件映射表
const nativeEventListeners: Record<string, (data: any) => void> = {};

// 暴露给原生调用的全局方法
(window as any).onNativeEvent = (event: string, data: string) => {
  const listener = nativeEventListeners[event];
  if (listener) {
    listener(JSON.parse(data));
  }
};

export function useEventCallBack(event: string, callback: (data: any) => void) {
  useEffect(() => {
    nativeEventListeners[event] = callback;

    // 清理
    return () => {
      delete nativeEventListeners[event];
    };
  }, [event, callback]);
}

export { NATIVE_EVENT };

原生代码需要知道这个入口:window.onNativeEvent("login_success", "{\"token\":\"abc\"}")


✅ 3. useEventBus:向原生发送事件

ts 复制代码
// hooks/useEventBus.ts
export default function useEventBus() {
  const sendToNative = (event: string, data?: any) => {
    const message = { event, data };

    // 【Android & HarmonyOS】
    if (window.AndroidBridge) {
      window.AndroidBridge.sendMessage(JSON.stringify(message));
    }

    // 【iOS】WKWebView postMessage
    else if (window.webkit?.messageHandlers?.NativeHandler) {
      window.webkit.messageHandlers.NativeHandler.postMessage(message);
    }

    // 【HarmonyOS ArkWeb】可能有自己的 bridge
    else if ((window as any).ArkJSBridge) {
      (window as any).ArkJSBridge.call(JSON.stringify(message));
    }

    // 开发环境模拟
    else {
      console.warn('[Mock] Send to Native:', message);
    }
  };

  return { sendToNative };
}

✅ 五、实际使用案例

示例 1:H5 请求原生打开相机

tsx 复制代码
function CameraButton() {
  const { sendToNative } = useEventBus();

  const handleClick = () => {
    sendToNative('open_camera', { resolution: 'high' });
  };

  return <button onClick={handleClick}>打开相机</button>;
}

示例 2:监听原生返回键事件

tsx 复制代码
function BackListener() {
  useEventCallBack(NATIVE_EVENT.BACK_BUTTON, (data) => {
    console.log('用户点击了返回键', data);
    // 执行某些逻辑,比如退出当前页
  });

  return null; // 不渲染 UI
}

示例 3:监听登录成功事件

tsx 复制代码
function AuthListener() {
  useEventCallBack(NATIVE_EVENT.LOGIN_SUCCESS, (data) => {
    console.log('原生登录成功:', data.token);
    // 存储 token,更新状态
    commonStore.setToken(data.token);
  });

  return null;
}

✅ 六、原生端配合示例(伪代码)

Android / HarmonyOS(Java/Kotlin/ArkTS)

java 复制代码
// Android WebView
webView.evaluateJavascript(
  "onNativeEvent('login_success', '{\"token\":\"abc123\"}')",
  null
);

iOS(Swift)

swift 复制代码
webView?.evaluateJavaScript("onNativeEvent('pay_result', '{\"status\":\"success\"}')")

✅ 七、兼容性建议

平台 推荐通信方式
Android addJavascriptInterface 或自定义 JSBridge
iOS (WKWebView) webkit.messageHandlers
HarmonyOS ArkWeb 支持 @Concurrent + JSBridge
调试阶段 使用 vConsole 打印日志

✅ 总结

目标 实现方式
H5 → 原生 useEventBus().sendToNative() 调用原生方法
原生 → H5 原生执行 JS 触发 onNativeEvent(eventName, data)
统一事件管理 使用 NATIVE_EVENT 枚举定义事件名
防止耦合 封装成 Hook,便于复用和测试
相关推荐
CocoaKier14 小时前
苹果谷歌商店:如何监控并维护用户评分评论
ios·google·apple
不爱说话郭德纲14 小时前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
iOS日常15 小时前
iOS设备崩溃日志获取与查看
ios·xcode
Sinclair18 小时前
简单几步,安卓手机秒变服务器,安装 CMS 程序
android·服务器
SummerKaze21 小时前
为鸿蒙开发者写一个 nvm:hmvm 的设计与实现
harmonyos
雮尘21 小时前
手把手带你玩转Android gRPC:一篇搞定原理、配置与客户端开发
android·前端·grpc
wangruofeng1 天前
AI 助力 Flutter 3.27 升级到 3.38 完整指南:两周踩坑与实战复盘
flutter·ios·ai编程
ktl1 天前
Android 编译加速/优化 80%:一个文件搞定,零侵入零配置
android
alexhilton1 天前
使用FunctionGemma进行设备端函数调用
android·kotlin·android jetpack
冬奇Lab2 天前
InputManagerService:输入事件分发与ANR机制
android·源码阅读