通过 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,便于复用和测试
相关推荐
草莓熊Lotso15 小时前
脉脉独家【AI创作者xAMA第二期】| 从拼图游戏到AI设计革命
android·开发语言·c++·人工智能·脉脉
肖。354878709415 小时前
html选择页最简模板源码,用于集合很多网页!游戏大全数字导航页面,数字选择页制作灵感,已经压缩到最小,现代,讲解。
android·java·javascript·css·html
qq_1777673715 小时前
React Native鸿蒙跨平台完成动漫应用实现本地数据持久化、收藏管理、观看历史记录、标签页切换
javascript·react native·react.js·ecmascript·harmonyos
ujainu15 小时前
Flutter + OpenHarmony 实战:从零开发小游戏(二)——轨道跳跃与动态关卡生成
flutter·游戏·harmonyos
m0_7482331717 小时前
PHP7.4重磅特性全解析
android
大雷神17 小时前
HarmonyOS智慧农业管理应用开发教程--高高种地-- 第24篇:学习中心 - 课程体系设计
大数据·学习·harmonyos
蜗牛、Z17 小时前
Android 日常开发Adb常用命令附档
android·adb
一起养小猫18 小时前
Flutter for OpenHarmony 实战:打造天气预报应用
开发语言·网络·jvm·数据库·flutter·harmonyos
小白郭莫搞科技1 天前
鸿蒙跨端框架Flutter学习:CustomTween自定义Tween详解
学习·flutter·harmonyos
mocoding1 天前
使用鸿蒙化flutter_fluttertoast替换Flutter原有的SnackBar提示弹窗
flutter·华为·harmonyos