uni-app 的 web-view 不支持直接加载本地 HTML 文件,H5 端报 404、小程序端白屏;跨平台需用 uni.request 拉取 HTML 字符串 + v-html 渲染或本地 HTTP Server;通信依赖 postMessage/onMessage;web-view 中需手动引入 uni-app-bridge.js 才能使用 uni.postMessage;Android 端需启用 X5 内核并避免 async/await 和复杂 CSS。

web-view 加载本地 HTML 文件打不开
uni-app 的 web-view 默认不支持直接加载本地 static 或 uni_modules 下的 HTML 文件(如 web-view src="/static/page.html"),H5 端会报 404,小程序端直接白屏或提示“网页解析失败”。这是因为不同平台对本地资源协议限制不同:微信小程序只认 https:// 或 http://,H5 虽能读本地文件但受限于跨域和路径解析规则。
正确做法是把 HTML 放进 static 目录后,用 uni.loadSubNVue 或服务端托管——但更通用、零配置的方式是改用 uni-app 内置的 web-view 协议:__uniapp-webview__。不过该协议仅限 H5 平台;真要跨平台加载本地页面,必须走 uni.request 拉取 HTML 字符串,再用 v-html 渲染(注意 XSS 风险)或起一个本地 HTTP Server(开发阶段可用 http-server 启一个 static 目录)。
- 小程序端必须用 HTTPS 域名,连
localhost都不认,哪怕在开发者工具里也不行 - H5 端若用相对路径,确保路径相对于最终生成的
index.html,不是源码路径 - 调试时用
console.log(uni.getSystemInfoSync())确认当前平台,避免写死src
web-view 和 Vue 页面之间怎么传参
web-view 是独立渲染容器,和 Vue 页面不在同一 JS 上下文,不能直接调用方法或访问 data。通信只能靠平台提供的桥接机制:H5 用 window.postMessage + window.addEventListener('message'),小程序用 web-view 的 postMessage 和 onMessage 生命周期。
关键点在于:Vue 页面向 web-view 发消息,得等 web-view 加载完成(@load 触发后);web-view 向 Vue 页面发消息,需在页面 JS 中监听 message 事件(H5)或在 onMessage 回调中处理(小程序)。两者参数结构也不同——H5 的 postMessage 只接受可序列化对象,小程序则要求顶层字段为 data。
- H5 端发送:
this.$refs.webview.$el.contentWindow.postMessage({type: 'init', token: 'xxx'}, '*') - 小程序端接收:在
web-view标签上加@message="onWebMessage",函数里取event.detail.data - 别在
mounted就发消息,web-view还没 ready,得等@load后再调用postMessage
web-view 里调用 uni API 报错 “not defined”
web-view 加载的 HTML 页面运行在独立 Webview 实例中,uni 对象默认不可见。想用 uni.showToast 或 uni.navigateBack,必须手动注入 bridge 脚本。uni-app 提供了 uni.webView.postMessage 和预置的 uni-app-bridge.js,但这个脚本不会自动加载,得自己引入。
实际操作分两步:先在 web-view 加载的 HTML 里通过 <script src="/static/uni-app-bridge.js"></script> 引入(该文件需从 node_modules/@dcloudio/uni-cli-shared 复制出来放 static);再确保页面 JS 中调用的是 uni.postMessage(发给 Vue 页面)而非直接调 uni.showToast——后者仍不可用,真正能用的只有 uni.postMessage 和监听 message 事件。
- 别指望
uni.getSystemInfo在 web-view 里直接运行,它不存在 - 如果只是想关掉 web-view,最稳方式是 Vue 页面监听到消息后执行
uni.navigateBack() - 注入脚本后,
uni.postMessage发送的数据会在 Vue 页面的onMessage或message事件里收到,格式统一为{data: {...}}
Android 上 web-view 白屏或卡死
这是最常被忽略的兼容问题:Android 微信 SDK(尤其 8.0.33+)和部分国产浏览器内核对 web-view 的 GPU 加速、iframe 嵌套、CSS transform 层叠有严格限制。常见表现是页面加载一半就停住、滚动卡顿、点击无响应,但控制台无报错。
根本原因不是代码写错,而是渲染管线被阻塞。解决方案不是重写逻辑,而是降级渲染策略:禁用硬件加速、减少 CSS 动画层级、避免在 web-view 里嵌套另一个 web-view 或 iframe。另外,uni-app 的 web-view 组件在 Android 上默认使用系统 WebView,而很多低端机系统 WebView 版本极老(如 Android 6 的 44.x),连 ES6 的 Promise 都不支持。
- 在
manifest.json的 “Android 设置” 里勾选 “使用 X5 内核”,可大幅提升兼容性(需接入腾讯 X5 SDK) - web-view 页面 JS 中避免用
async/await,改用Promise.then,并手动引入promise-polyfill - 别在
web-view里做长列表虚拟滚动,用原生scroll-view替代更可靠
事情说清了就结束










