通过 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,便于复用和测试
相关推荐
恋猫de小郭3 小时前
Flutter 也有类 React Flow 的节点流程编辑器,快来了解下刚刚开源的 vyuh_node_flow
android·前端·flutter
2501_916008893 小时前
iOS 26 文件导出与数据分析,多工具组合下的开发者实践指南
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_916008893 小时前
iOS混淆实战用多工具组合把IPA加固做成可复用的工程能力(iOS混淆 IPA加固 无源码混淆
android·ios·小程序·https·uni-app·iphone·webview
wangdaoyin20103 小时前
UniApp 在手机端(Android)打开选择文件和文件写入
android·前端·uni-app
爱笑的眼睛114 小时前
HarmonyOS Text组件样式定制深度解析:从基础到高级实践
华为·harmonyos
ChinaDragon4 小时前
HarmonyOS:弹出框层级管理
harmonyos
我命由我123454 小时前
Android PDF 操作 - AndroidPdfViewer 显示 PDF 异常清单(数据为 null、数据为空、PDF 文件损坏、非 PDF 文件)
android·java·java-ee·pdf·android studio·android-studio·android runtime
爱笑的眼睛115 小时前
鸿蒙应用开发:华为静默登录解决方案
华为·harmonyos
zhilin_tang5 小时前
揭开Linux跨平台 adb调试原理神秘面纱
android·linux