H5 与 WebView 的双向通信实现详解

背景介绍

在混合开发中,H5 页面与原生应用的通信是一个常见需求。本文将详细介绍如何实现 H5 与 React Native WebView 之间的双向通信机制。

核心实现

首先,我们需要在 H5 端实现一个回调管理器,用于处理与原生端的通信:

1. H5 端完整实现

// 回调管理器
window.NativeCallbacks = {callbacks: {},register: function(type, successCallback, errorCallback) {const callbackId = type + Date.now().toString();// Promise方式if (!successCallback && !errorCallback) {const promise = new Promise((resolve, reject) => {this.callbacks[callbackId] = {success: resolve,error: reject,};});return {promise,callbackId};}// 回调方式this.callbacks[callbackId] = {success: successCallback, error: errorCallback,};return callbackId;},execute: function(callbackId, type, data) {const callback = this.callbacks[callbackId];if (callback) {if (type === 'success') {callback.success && callback.success(data);} else {callback.error && callback.error(data);}delete this.callbacks[callbackId]; // 执行后清理回调}}
};// 原生通信接口封装
window.Native = {// 回调方式getUserInfo: function(successCallback, errorCallback) {const callbackId = ntalkCallbacks.register('getUserInfo', successCallback, errorCallback);window.ReactNativeWebView.postMessage(JSON.stringify({type: 'getUserInfo',callbackId,data: null}));},// Promise方式getUserInfoAsync: async function() {const { promise, callbackId } = ntalkCallbacks.register('getUserInfo');window.ReactNativeWebView.postMessage(JSON.stringify({type: 'getUserInfo',callbackId,data: null}));return promise;}
};

2. React Native 端完整实现

interface MessageData {type: string;callbackId: string;data: any;
}class WebViewManager {private webview: WebView;constructor(webview: WebView) {this.webview = webview;}handleMessage(message: string) {try {const data: MessageData = JSON.parse(message);const { type, callbackId, data: payload } = data;switch(type) {case 'getUserInfo':this.handleGetUserInfo(callbackId, payload);break;case 'setAppCacheValue':this.handleSetAppCache(callbackId, payload);break;default:this.sendCallback(callbackId, 'error', '未知的消息类型');}} catch (error) {console.error('消息处理错误:', error);}}sendCallback(callbackId: string, type: 'success' | 'error', data: any) {const script = `window.ntalkCallbacks.execute('${callbackId}','${type}',${JSON.stringify(data)});`;this.webview.injectJavaScript(script);}private handleGetUserInfo(callbackId: string, payload: any) {try {// 实际项目中从本地存储或状态管理中获取const userInfo = {userId: '123',name: '张三',avatar: 'https://example.com/avatar.png'};this.sendCallback(callbackId, 'success', userInfo);} catch (error) {this.sendCallback(callbackId, 'error', error.message);}}private handleSetAppCache(callbackId: string, payload: any) {try {const { key, value } = payload;// 实际项目中进行缓存操作this.sendCallback(callbackId, 'success', true);} catch (error) {this.sendCallback(callbackId, 'error', error.message);}}
}// WebView 组件使用示例
function MyWebView() {const webViewRef = useRef<WebView>(null);const webViewManager = useRef<WebViewManager>();useEffect(() => {if (webViewRef.current) {webViewManager.current = new WebViewManager(webViewRef.current);}}, []);return (<WebViewref={webViewRef}source={{ uri: 'https://example.com' }}onMessage={(event) => {webViewManager.current?.handleMessage(event.nativeEvent.data);}}/>);
}

3. 使用示例

// 示例1:回调方式
Native.getUserInfo((userInfo) => {console.log('获取用户信息成功:', userInfo);},(error) => {console.error('获取用户信息失败:', error);}
);// 示例2:Promise方式
async function getUserData() {try {const userInfo = await ntalkNative.getUserInfoAsync();console.log('获取用户信息成功:', userInfo);} catch (error) {console.error('获取用户信息失败:', error);}
}

通信流程图解

H5 原生 1. 调用 Native 方法 2. 注册回调函数 3. 发送 postMessage 4. 处理业务逻辑 5. 注入回调脚本 6. 执行回调并清理 H5 原生

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/496030.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解线性方程组

直接三角分解&#xff08;LU分解&#xff0c;Doolittle分解&#xff09; ATM分解&#xff08;追赶法&#xff0c;Crout分解&#xff0c;克劳特分解&#xff09; 平方根法&#xff08;Cholesky分解&#xff0c;乔列斯基分解&#xff09; 矩阵的范数

实现点击表格中的邀请码并复制到剪贴板的功能

文章目录 实现步骤修改代码1. 添加复制邀请码的处理函数2. 在表格列中添加点击事件3. 添加样式完整的 invite-code-list.vue 文件 要实现点击表格中的邀请码并复制到剪贴板的功能&#xff0c;可以使用 JavaScript 的 Clipboard API。以下是如何在你的 invite-code-list.vue 文…

clickhouse解决suspiciously many的异常

1. 问题背景 clickhouse安装在虚拟机上&#xff0c;持续写入日志时&#xff0c;突然关机&#xff0c;然后重启&#xff0c;会出现clickhouse可以正常启动&#xff0c;但是查询sql语句&#xff0c;提示suspiciously many异常&#xff0c;如图所示 2. 问题修复 touch /data/cl…

本原多项式

将 G F ( p ) GF(p) GF(p)延伸为有 p m p^m pm个元素的域&#xff0c;称之为 G F ( p ) GF(p) GF(p)的扩域&#xff0c;表示为 G F ( p m ) GF(p^m) GF(pm). G F ( p ) GF(p) GF(p)是 G F ( p m ) GF(p^m) GF(pm)的子集。 G F ( p m ) GF(p^m) GF(pm)元素个数为 p m p^m pm。 …

编译openssl遇到错误Parse errors: No plan found in TAP output的解决方法

在编译openssl时 tar -zxvf openssl-1.1.1p.tar.gz cd openssl-1.1.1p ./config --prefix/usr --openssldir/etc/ssl --shared zlib make make test 遇到错误 Parse errors: No plan found in TAP output 解决方法&#xff1a; yum install perl-Test-Simple

Milvus×EasyAi:如何用java从零搭建人脸识别应用

如何从零搭建一个人脸识别应用&#xff1f;不妨试试原生Java人工智能算法&#xff1a;EasyAi Milvus 的组合拳。 本文将使用到的软件和工具包括&#xff1a; EasyAi&#xff1a;人脸特征向量提取Milvus&#xff1a;向量数据库用于高效存储和检索数据。 01. EasyAi&#xff1a;…

7.C语言 宏(Macro) 宏定义,宏函数

目录 宏定义 宏函数 1.注释事项 2.注意事项 宏(Macro)用法 常量定义 简单函数实现 类型检查 条件编译 宏函数计算参数个数 宏定义进行类型转换 宏定义进行位操作 宏定义进行断言 总结 宏定义 #include "stdio.h" #include "string.h" #incl…

EdgeX Core Service 核心服务之 Core Command 命令

EdgeX Core Service 核心服务之 Core Command 命令 一、概述 Core-command(通常称为命令和控制微服务)可以代表以下角色向设备和传感器发出命令或动作: EdgeX Foundry中的其他微服务(例如,本地边缘分析或规则引擎微服务)EdgeX Foundry与同一系统上可能存在的其他应用程序…

19_HTML5 Web Workers --[HTML5 API 学习之旅]

HTML5 Web Workers 是一种允许 JavaScript 在后台线程中运行的技术&#xff0c;从而不会阻塞用户界面或其他脚本的执行。通过使用 Web Workers&#xff0c;你可以执行复杂的计算任务而不影响页面的响应速度&#xff0c;提升用户体验。 Web Workers 的特点 Web Workers 是 HTM…

数据分析篇001

目录 一、数据是什么&#xff1f; 二、数据能做什么&#xff1f; 三、数据应用四步骤 第一步---搭建数据体系 第二步---积累数据资产 第三步---完成数据分析 第四步---实现数据应用 四、数据的三种性质 变异性 规律性&#xff08;以正态分布为例&#xff09; 客观性…

Java线程池面试题

为什么要用线程池 降低资源消耗&#xff1a;通过重复利用已创建的线程降低线程创建和销毁造成的消耗提高响应速度&#xff1a;当任务到达时&#xff0c;任务可以不需要等到线程创建就能立即执行方便管理线程&#xff1a;线程是稀缺资源&#xff0c;如果无条件地创建&#xff0…

校史馆云展厅适合远程教学吗?

随着信息技术的飞速发展&#xff0c;远程教学已经成为教育领域的一个重要趋势。 校史馆作为学校文化传承的重要场所&#xff0c;承载着丰富的历史信息和教育资源。 那么&#xff0c;将校史馆搬到云端&#xff0c;构建云展厅&#xff0c;是否适合远程教学呢&#xff1f; 下面…

【安全编码】Web平台如何设计防止重放攻击

我们先来做一道关于防重放的题&#xff0c;答案在文末 防止重放攻击最有效的方法是&#xff08; &#xff09;。 A.对用户密码进行加密存储使用 B.使用一次一密的加密方式 C.强制用户经常修改用户密码 D.强制用户设置复杂度高的密码 如果这道题目自己拿不准&#xff0c;或者…

GJB289A总线典型网络理论分析

1.GJB289A总线典型网络理论分析 根据相关标准&#xff0c;“某个支路的故障不影响整个系统”及耦合变压器特性&#xff0c;本文在仿真与实测时均采用典型的一发一收两端口总线网络。 典型两端口总线网络电气结构如图1所示&#xff0c;包含终端匹配电阻、故障隔离电阻、耦合变…

基于SpringBoot的4S店汽车销售管理系统的设计与实现

一、课题背景 为汽车销售公司设计了一个汽车管理系统 技术&#xff1a;前台采用网页技术&#xff0c;后端采用SpringBoottMybatistvue 项目 描述&#xff1a;随着人们生活水平的不断提高&#xff0c;人们对汽车的消费和需求也越来越旺盛。多汽车销售公司仍然采用人工记账的传…

SQL子查询和having实例

有2个表如下&#xff1b;一个是站点信息&#xff0c;一个是站点不同时间的访问量&#xff0c; 现在要获取总访问量大于200的网站&#xff1b; 先执行如下sql&#xff0c;不包括having子句看一下&#xff0c;获得的是所有站点的总访问量&#xff1b; 这应是一个子查询&#xf…

SpringAI人工智能开发框架006---SpringAI多模态接口_编程测试springai多模态接口支持

可以看到springai对多模态的支持. 同样去创建一个项目 也是跟之前的项目一样,修改版本1.0.0 这里 然后修改仓库地址,为springai的地址 然后开始写代码

【UE5 C++课程系列笔记】13——GameInstanceSubsystem的简单使用

目录 概念 基本使用案例 效果 步骤 概念 UGameInstanceSubsystem 类继承自 USubsystem&#xff0c;它与 GameInstance 紧密关联&#xff0c;旨在为游戏提供一种模块化、可方便扩展和管理的功能单元机制。在整个游戏运行期间&#xff0c;一个 GameInstance 可以包含多个 UGa…

mac_录屏

参考&#xff1a; mac m1上系统内录方法BlackHole代替soundflower录音(附安装包) https://blog.csdn.net/boildoctor/article/details/122765119录屏后没声音&#xff1f;这应该是 Mac&#xff08;苹果电脑&#xff09; 内录声音最优雅的解决方案了 https://www.bilibili.com/…

CTF MISC 简单的脚本的撰写 -- 进制转换篇

前言 为什么学习 脚本 &#xff1f; 当脚本小子的基础也是需要看懂代码的好吧 虽然很多工具都可以解码 进制转换 ascii 但是 前 128位的ascii 可以转 那后 128位呢 一般工具是不识别的所以脚本还需自己学 【ASCII】完整ascii码表0-127 扩展表128-255-CSDN博客 前言知识…