实现方案
1. 消息格式设计:
- 网页向 APP 发送的消息格式:采用 JSON 结构,包含 type (消息类型)、 data ( payload 数据)和 callbackId (唯一标识每个请求的回调函数)
- 消息格式示例:
go
{
type: 'GET_USER_INFO', // 消息类型
data: { id: '123456' }, // 消息内容
callbackId: 'cb_1698850392834_0.3255338999917584' // 回调标识
}
2. 回调函数管理:
- 网页端使用全局对象 window.__webview_callbacks 存储回调函数
- 通过 callbackId 实现请求-响应的精准匹配
- 内置 60 秒超时清理机制,防止内存泄漏
3.消息传递机制:
- H5 → App:网页通过 uni.webView.postMessage() 发送消息到 App
- App 通过 @message 事件监听来自网页的消息
- App → H5:通过 evalJS() 执行 H5 端的 handleAppCallback() 函数
3. 跨平台兼容:
- 实际应用中应添加平台判断逻辑,实现跨平台兼容
具体实现
H5端核心代码
引入uni.webview.1.5.5.js文件,调用uni.webview.postMessage()方法,向web-view发送消息。
xml
<script type="text/javascript" src="uni.webview.1.5.5.js"></script>
xml
<script type="text/javascript">
// 消息回调映射表(用于处理异步回调)
const callbackMap = new Map()
// 发送消息到 APP
function postToApp(messageType, payload, callback) {
const callbackId = `cb_${Date.now()}_${Math.random().toString(36).substr(2)}`
// 注册回调
if (typeof callback === 'function') {
callbackMap.set(callbackId, callback)
// 将回调函数存储到全局对象中
window.__webview_callbacks = window.__webview_callbacks || {};
window.__webview_callbacks[callbackId] = callback;
}
// 发送消息
uni.webView.postMessage({
data: {
type: messageType,
data: payload,
callbackId: callbackId
}
})
}
// 处理来自App的回调
function handleAppCallback(callbackId, result) {
if (window.__webview_callbacks && window.__webview_callbacks[callbackId]) {
window.__webview_callbacks[callbackId](result);
// 执行完回调后删除该回调函数
delete window.__webview_callbacks[callbackId];
}
}
// 添加超时清理机制,避免内存泄漏
setInterval(() => {
callbackMap.forEach((callback, callbackId) => {
if (callbackMap.has(callbackId)) {
callbackMap.delete(callbackId)
delete window.__webview_callbacks[callbackId];
console.warn(`Callback ${callbackId} timeout`)
}
})
}, 60_000) // 60秒检查一次
// 调用示例,获取用户信息
function getUserInfo() {
postToApp('GET_USER_INFO', {
id: '233333'
}, (response) => {
if (response.status === 'success') {
console.log('User Info:', response.data)
} else {
console.error('Error:', response.message)
}
})
}
</script>
uni-app x端核心代码
在web-view组件上监听@message事件,处理来自H5的消息。
xml
<template>
<view class="container">
<web-view :src="webViewUrl" :onMessage="handleMessage" />
</view>
</template>
<script>
export default {
data() {
return {
webViewUrl: 'https://...'
}
},
methods: {
handleMessage(event) {
console.log('接收到的消息:', event.data); // 打印接收到的消息
// 在这里处理接收到的消息
let data = event.detail.data[0]
if( data.type == 'GET_USER_INFO'){
console.log("-----------GET_USER_INFO-------")
let callbackId = data.callbackId
const webview = uni.getElementById('web-view') as UniWebViewElement
let result = {
status: 'success',
data: {
name: '张三'
}
}
let res = JSON.stringify(result)
const callbackScript = `handleAppCallback('${callbackId}', ${res});`;
webview.evalJS(callbackScript)
return
}
}
}
}