当前位置: 首页 > news >正文

通过 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 → 原生(发送事件)

// 方式一:调用原生暴露的方法(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 注册的回调函数:

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

或者直接调用全局函数:

window.onNativeLoginSuccess && window.onNativeLoginSuccess(res);

✅ 三、结合你的代码分析

import useEventBus from '@/hooks/useEventBus';
import { NATIVE_EVENT, useEventCallBack } from './hooks/useEventCallBack';

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

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

✅ 四、具体实现示例

✅ 1. 定义原生事件常量

// 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:监听原生事件

// 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:向原生发送事件

// 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 postMessageelse if (window.webkit?.messageHandlers?.NativeHandler) {window.webkit.messageHandlers.NativeHandler.postMessage(message);}// 【HarmonyOS ArkWeb】可能有自己的 bridgeelse 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 请求原生打开相机

function CameraButton() {const { sendToNative } = useEventBus();const handleClick = () => {sendToNative('open_camera', { resolution: 'high' });};return <button onClick={handleClick}>打开相机</button>;
}

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

function BackListener() {useEventCallBack(NATIVE_EVENT.BACK_BUTTON, (data) => {console.log('用户点击了返回键', data);// 执行某些逻辑,比如退出当前页});return null; // 不渲染 UI
}

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

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

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

Android / HarmonyOS(Java/Kotlin/ArkTS)

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

iOS(Swift)

webView?.evaluateJavaScript("onNativeEvent('pay_result', '{\"status\":\"success\"}')")

✅ 七、兼容性建议

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

✅ 总结

目标实现方式
H5 → 原生useEventBus().sendToNative() 调用原生方法
原生 → H5原生执行 JS 触发 onNativeEvent(eventName, data)
统一事件管理使用 NATIVE_EVENT 枚举定义事件名
防止耦合封装成 Hook,便于复用和测试
http://www.dtcms.com/a/540643.html

相关文章:

  • iOS 26 iPhone 使用记录分析 多工具组合构建全方位设备行为洞察体系
  • 【Unity】HTModuleManager(三)Markdown语法的Unity编辑器方言
  • 如何将安卓手机备份到电脑?7种方法
  • 基于SpringBoot+Vue的购物商城(支付宝沙盒支付、物流快递API、WebSocket及时通讯、协同过滤算法、Echarts图形化分析)
  • MYSQL-超全基础以及用法--仅个人的速记笔记(1)
  • 31、LangChain开发框架(八)-- LangChain 数据分析智能体实战
  • 建设局域网网站盐城市亭湖区城乡建设网站
  • 6.2 大数据方法论与实践指南-任务元数据
  • MongoDB中全文索引基础篇
  • SSM浪漫烘焙屋z73z2(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 网站网域名查询外贸推广的几种方式以及效果排行
  • 彩票网站做代理网站建设与管理规定
  • 系统商(ERP、OMS、WMS 等)打通物流 API 数据的重要一环
  • kubectl 学习心得:从入门到实践的 K8s 命令行掌控之旅
  • 非线性笔记革命:Trilium+cpolar如何让知识管理突破时空限制?
  • 华为ENSP——OSPF多区域配置实验
  • 快指点击器 1.1.9 | 支持多点操作、自动化脚本,操作记录等功能,快速解放双手
  • Termux 安装 Joplin Server ,全平台同步Joplin笔记
  • 笔记:现代操作系统:原理与实现(6)
  • 电商网站对比表请问下网站开发怎么弄
  • 浙人医已用金仓 KFS 工具破解多数据库并存难题!
  • 四川建设网网站首页开发公司起名
  • K8s学习笔记(二十四) ingress
  • 将axios、async、Promise联系在一起讲一下讲一下.then 与其关系
  • 最权威的排行榜网站scratch网站开发
  • WPF 数据绑定详解
  • 【Swift】LeetCode 54. 螺旋矩阵
  • 河北邯郸seo网站建设网站优化专业网站的定义
  • Python测试题2
  • WordPress 上传图片报错:明明是 PNG,却提示「请转换为 JPEG 或 PNG 格式」?