通过 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,便于复用和测试
相关推荐
白茶三许16 小时前
【江鸟中原】“策无忧” 决策模型纯血鸿蒙项目开发
华为·harmonyos
2501_9371892317 小时前
2025 优化版神马影视 8.8 源码系统|零基础部署
android·源码·开源软件·源代码管理·机顶盒
马剑威(威哥爱编程)17 小时前
【鸿蒙开发案例篇】鸿蒙跨设备实时滤镜同步的完整方案
华为·harmonyos
モンキー・D・小菜鸡儿19 小时前
Android Jetpack Compose 基础控件介绍
android·kotlin·android jetpack·compose
无风之翼19 小时前
android15 休眠唤醒过程中有时候屏幕显示时间一闪而过
android·锁屏
如此风景21 小时前
iOS SwiftUI开发所有修饰符使用详解
ios
mumuWorld21 小时前
KSCrash 实现机制深度分析
ios·源码阅读
方白羽21 小时前
Android全局悬浮拖拽视图
android·app·客户端
AskHarries1 天前
Google 登录问题排查指南
flutter·ios·app
waeng_luo1 天前
[鸿蒙2025领航者闯关] HarmonyOS深色模式实现
harmonyos·鸿蒙2025领航者闯关·鸿蒙6实战·开发者年度总结