通过 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,便于复用和测试
相关推荐
2501_915909067 分钟前
iOS App 测试工具全景指南,构建从开发、性能到系统级调试的多工具协同测试体系
android·测试工具·ios·小程序·uni-app·iphone·webview
钮钴禄·爱因斯晨13 分钟前
Python常见的文件操作
android·数据库·python
用户20187928316722 分钟前
希腊字母"Έ"显示不全的奇妙冒险
android
Entropless25 分钟前
Kotlin 可以预判你的预判?Kotlin 高级特性 之 Contracts
android·kotlin
AskHarries43 分钟前
RevenueCat 接入 Apple App Store 订阅全流程详解(2025 最新)
flutter·ios·app
雨白1 小时前
深入理解 Flow 的终端操作符
android
杜子不疼.2 小时前
【C++】深入解析AVL树:平衡搜索树的核心概念与实现
android·c++·算法
白茶三许2 小时前
关于Flutter版本过低导致鸿蒙虚拟机启动失败的问题解决
flutter·开源·harmonyos·openharmony
ajassi20003 小时前
开源 Objective-C IOS 应用开发(十三)通讯--Http访问
ios·开源·objective-c
游戏开发爱好者83 小时前
Fiddler抓包工具完整教程 HTTPHTTPS抓包、代理配置与API调试实战技巧(开发者进阶指南)
前端·测试工具·ios·小程序·fiddler·uni-app·webview