在鸿蒙平台做混合开发时,uni-app x 的 web-view 是嵌入网页的标准方案。原文明确,HarmonyOS 4.61 版本开始支持该组件。它的定位很直接:页面里的网页容器,可加载 H5、第三方网站和本地 HTML,并支持加载进度条、前后进导航、原生与 Web 通信、嵌套滚动等能力。鸿蒙平台底层使用系统 WebView 组件,缓存由系统管理。
一、基础用法与平台差异
最小用法是给定 src:- <template>
- <web-view src='https://www.baidu.com'></web-view>
- </template>
复制代码 这里最需要注意平台差异:Web 和小程序平台的 web-view 是全屏的,一个页面只能放一个 web-view,宽高设置会被忽略;App 平台可以自由调整大小和位置,适合做非全屏嵌入。鸿蒙平台支持在 scroll-view、list-view 中嵌套 web-view,默认开启嵌套滚动:优先滚动 web 页面内容,web 页面内容无法滚动时再滚动外层容器;可通过 android-nested-scroll 属性控制。嵌套滚动在 Android 与 iOS 上还有行为差异:Android 优先滚动 web 内容,无法滚动时滚动外层;iOS 需要 web 滚动条消失后才能滚动外层。实际适配时,建议先在目标平台验证外层容器滚动链路。
二、加载状态与错误处理
加载网页时,可监听 @loading、@load、@error。原文示例:- <template>
- <web-view :src='url'
- @loading='onLoading' @load='onLoad' @error='onError'></web-view>
- </template>
- <script setup lang='uts'>
- const url = ref('https://www.baidu.com')
- const onLoading = (event: UniWebViewLoadingEvent) => {
- console.log('开始加载:', event.detail.src)
- }
- const onLoad = (event: UniWebViewLoadEvent) => {
- console.log('加载完成:', event.detail.src)
- }
- const onError = (event: UniWebViewErrorEvent) => {
- console.log('加载失败:', event.detail.errMsg)
- console.log('错误码:', event.detail.errCode)
- }
- </script>
复制代码 原文列出的错误码为:100001 表示 SSL 错误,100002 表示页面错误,100003 表示 HTTP 错误。@error 的错误信息可能不够详细,建议结合 @loading 和 @load 一起判断加载状态。
三、本地 HTML 与路径规则
本地 HTML 只能访问 /static 目录下的文件,其他目录不会被打包,无法访问。示例:- <web-view src='/static/web/index.html'></web-view>
复制代码 鸿蒙平台文件路径大小写敏感。本地 HTML 引用的资源路径必须与实际文件名大小写一致,建议在构建资源命名时统一规则。这个点对跨平台迁移尤其重要:在大小写不敏感的系统上能跑,在鸿蒙上可能直接变成资源找不到。
四、原生与 Web 通信
网页端通过 uni.postMessage 向原生应用发送消息,原生用 @message 接收:- <template>
- <web-view src='/static/web/bridge.html'
- @message='onMessage'></web-view>
- </template>
- <script setup lang='uts'>
- const onMessage = (event: UniWebViewMessageEvent) => {
- console.log('收到消息:', event.detail.data)
- // data 是 UTSJSONObject[] 数组
- }
- </script>
复制代码 网页端发送:- <!-- /static/web/bridge.html -->
- <script>
- uni.postMessage({
- data: {
- action: 'login',
- token: 'xxx'
- }
- })
- </script>
复制代码 这里有个容易踩的坑:@message 事件的 data 类型是 UTSJSONObject[] 数组,不是单个对象。网页端发送的数据会被包装成数组,解析时不要按单对象处理。
五、WebViewContext 控制导航
后退、前进、刷新、停止加载和获取当前 URL,需要通过 uni.createWebViewContext() 获取上下文对象,不能直接在 web-view 组件上设置:- const webViewContext = uni.createWebViewContext('myWebView')
- webViewContext.back()
- webViewContext.forward()
- webViewContext.reload()
- webViewContext.stop()
- webViewContext.getWebViewUrl({
- success: (res) => {
- console.log('当前URL:', res.url)
- }
- })
复制代码 如果要做带地址栏、前进后退按钮的浏览器式页面,App 平台可把输入框、web-view 和底部操作栏组合起来;Web/小程序平台则要接受全屏限制。
六、其他事件与鸿蒙原生对比
@download 可监听网页中的下载链接,事件里能拿到 url、contentLength、mimetype;@contentheightchange 可监听网页内容高度变化,拿到 height。自定义进度条样式可通过 :webview-styles 设置,例如 progress.color 为 #2196F3;设置 progress: false 可隐藏进度条。
鸿蒙原生开发中,网页使用 Web 组件:- // 鸿蒙原生写法
- Web({ src: 'https://www.baidu.com', controller: this.controller })
- .width('100%')
- .height(300)
- .javaScriptAccess(true)
- .onPageEnd(() => {
- console.log('加载完成')
- })
复制代码 对比来看,uni-app x 的 web-view 属性更丰富,进度条、通信、嵌套滚动等能力开箱即用。若页面以 H5 为主、原生只做壳和桥接,web-view 的接入成本更低;若需要深度控制 Web 内核、缓存或安全策略,则要评估鸿蒙原生 Web 组件方案。
七、踩坑清单
1. Web/小程序平台全屏,一个页面只能放一个,设置宽高无效;App 平台可自由调整。
2. 本地 HTML 只能放 /static 目录,其他目录不打包。
3. @message 的 data 是 UTSJSONObject[] 数组。
4. 后退前进需要 WebViewContext。
5. 嵌套滚动行为在 Android、iOS 上有差异,鸿蒙平台默认优先滚 web 再滚外层。
6. @error 信息可能不详细,要结合 @loading、@load 判断状态。
7. 鸿蒙平台路径大小写敏感,资源引用必须一致。
总结
web-view 是 uni-app x 连接原生与 Web 的桥梁。在鸿蒙平台使用时,先确认 HarmonyOS 4.61 及以上支持,再按平台差异决定全屏或非全屏布局;本地资源统一放 /static 并注意大小写;通信按 UTSJSONObject[] 解析;导航控制交给 WebViewContext;嵌套滚动优先依赖默认行为并用 android-nested-scroll 微调。很多原生实现复杂的页面,可以考虑用 web-view 加载 H5 完成,但错误处理、路径和平台滚动差异必须提前纳入测试。 |