uni.postmessage是dcloud封装的跨端安全通信入口,底层自动适配ios wkwebview、android x5/系统webview及小程序web-view,统一事件监听与序列化流程,比原生window.postmessage更可靠。

uni-app 内嵌 H5 与 App 通信,优先用 uni.postMessage,而不是原生 window.postMessage;后者在 iOS 和 Android(尤其 X5 内核)上行为不一致,容易丢消息或触发不到事件。
uni.postMessage 是什么,为什么必须用它
这是 DCloud 封装的跨端安全通信入口,底层会自动适配 iOS WKWebView、Android X5/系统 WebView、小程序 web-view 等不同容器。它不是简单转发 window.postMessage,而是统一了事件监听机制和数据序列化流程。
- 原生
window.parent.postMessage在 X5 内核中可能被静默拦截,且无法保证message事件在 Vue 实例生命周期内被正确绑定 -
uni.postMessage发出的消息,uni-app 的@message事件一定能收到,只要web-view组件已挂载并完成加载 - 不依赖
uni.webview.jsSDK 加载,也不需要监听UniAppJSBridgeReady,更轻量、更可靠
web-view 组件上如何接收 postMessage 消息
关键点在于:消息体始终在 e.detail.data 中,且是数组类型(即使只发一条),不是对象。
- 必须确保
web-view已渲染并触发过@load,否则@message可能丢失首条消息 - 不要对
e.detail.data做类型断言为对象,要先取[0]或遍历处理 - 推荐加防抖或标记位,避免重复处理同一批消息(比如用户快速点击多次分享按钮)
<template><web-view :src="h5Url"></web-view></template><script>
export default {
data() {
return {
loaded: false
}
},
methods: {
onLoad() {
this.loaded = true
},
onMessage(e) {
// 注意:e.detail.data 是数组!
const msgs = e.detail.data
msgs.forEach(msg => {
if (msg.action === 'share') {
uni.showShareMenu({}) // 触发原生分享
}
})
}
}
}
</script>
H5 页面里怎么发消息给 uni-app
H5 页面不需要引入任何 SDK,只要运行在 web-view 容器中,就能直接调用 uni.postMessage —— 这是 uni-app 注入的全局 API。
- 发送前务必检查
typeof uni !== 'undefined' && typeof uni.postMessage === 'function',防止 H5 被单独打开时报错 - 消息内容必须是纯 JSON 可序列化的对象(不能含
Date、Function、undefined、RegExp等) - 建议加
timestamp字段用于调试时判断消息时效性,避免旧消息误触发
// H5 页面中
if (typeof uni !== 'undefined' && typeof uni.postMessage === 'function') {
uni.postMessage({
data: {
action: 'loginSuccess',
userId: 'u_789012',
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
timestamp: Date.now()
}
})
} else {
console.warn('uni.postMessage not available')
}
常见错误和兼容性陷阱
最常踩的坑不在语法,而在环境判断和生命周期时机。
- Android 上某些低版本 X5 内核(如 4.3.x)会把
uni.postMessage当作未定义,需降级 fallback 到window.parent.postMessage+ 手动监听message事件 - iOS WKWebView 中,如果 H5 页面用了
history.pushState导致 URL 变化,可能重置通信上下文,后续uni.postMessage失效 - 微信小程序中,
web-view的@message事件只在页面首次加载后生效,页面内跳转(如a标签)不会重新绑定 - 别在 H5 的
DOMContentLoaded钩子中立刻发消息,应等uni对象注入完成,稳妥做法是setTimeout延迟 100ms 或监听UniAppJSBridgeReady
真正难的从来不是“怎么写”,而是“什么时候能写”——H5 页面是否已处于可通信上下文中,uni-app 是否已完成组件挂载,各端 WebView 内核是否悄悄改了行为。这些细节不验证,代码写得再标准也没用。











