App端需用HTTP(S)地址加载页面,通过webkit.messageHandlers.postMessage通信,且须等@ready后发送消息;H5和小程序需分别适配。
直接用 <web-view></web-view> 组件,但必须注意:app 端它不是 iframe,而是原生 webview(ios 用 wkwebview,android 用系统 webview 或 x5),和 vue 页面完全隔离 —— 所以别指望 window.uni 能直接调用,也别在网页里写 uni.postmessage(),那会报 typeerror: cannot read property 'postmessage' of undefined。
App 端 <web-view></web-view> 的 src 必须是 http(s) 协议
本地 HTML 文件(如 /static/page.html)在 App 端无法直接加载,H5 报 404,小程序直接白屏。这是因为:
- iOS/Android 原生 WebView 不支持
file://或uni-app://协议加载本地资源 - 微信小程序强制要求 HTTPS,连
http://localhost都不认 - H5 端虽能读本地文件,但受跨域和构建路径限制,实际不可靠
正确做法:
- 把 H5 页面部署到 HTTP(S) 服务上,
src填完整地址,例如"https://example.com/app-page.html" - 开发阶段可用
http-server启一个本地静态服务,再用局域网 IP 访问(如"http://192.168.1.100:8080/page.html") - 绝对不要写相对路径如
"./page.html"或"/static/page.html"
网页向 Vue 页面发消息:只靠 onMessage + postMessage
这是 App 端唯一可靠通路,H5 和小程序另有机制,不能混用。
Vue 页面中写:
<web-view src="https://example.com/page.html" @message="onWebMsg"></web-view>
网页 HTML 中(无需引入任何 SDK)写:
window.webkit.messageHandlers.uniWebview.postMessage({ action: 'loginSuccess', data: { token: 'abc123' } });
注意点:
- 该调用在 H5 环境会报错(
webkit.messageHandlers不存在),必须加运行时判断:if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.uniWebview) -
@message回调拿到的是event.detail.data,不是整个event.detail - 消息内容必须是可序列化对象,不能传函数、DOM 节点或
undefined
Vue 页面向网页发消息:必须等 @ready 触发后才安全
web-view 渲染完成前调用 postMessage 会静默失败,不报错但网页收不到。
正确写法:
<web-view ref="webview" :src="url" @ready="onWebReady" @message="onWebMsg"></web-view>
onWebReady 中再发:
this.$refs.webview.postMessage({ action: 'initConfig', data: { theme: 'dark' } });
网页侧监听:
window.addEventListener('message', e => { console.log(e.data); });
关键细节:
-
@ready比@load更可靠,它表示原生 WebView 实例已创建并就绪 - Android 上若启用 X5 内核,部分新版 API(如
async/await)可能不兼容,建议网页 JS 保持 ES6 兼容写法 - iOS WKWebView 对
postMessage的 payload 大小有限制(约 1MB),超限会被截断
最常被忽略的其实是平台差异本身:同一套通信代码,在 App 端走 webkit.messageHandlers,在 H5 端得降级为 window.parent.postMessage,而小程序又得走自己的 web-view.postMesssage。没做平台判断就上线,大概率只在一个端跑通。


















