查看: 1263|回复: 3

鸿蒙 uni-app x web-view 通信与嵌套滚动避坑

[复制链接]
发表于 昨天 15:00 | 显示全部楼层 |阅读模式
在鸿蒙平台做混合开发时,uni-app x 的 web-view 是嵌入网页的标准方案。原文明确,HarmonyOS 4.61 版本开始支持该组件。它的定位很直接:页面里的网页容器,可加载 H5、第三方网站和本地 HTML,并支持加载进度条、前后进导航、原生与 Web 通信、嵌套滚动等能力。鸿蒙平台底层使用系统 WebView 组件,缓存由系统管理。

一、基础用法与平台差异
最小用法是给定 src:
  1. <template>
  2.   <web-view src='https://www.baidu.com'></web-view>
  3. </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。原文示例:
  1. <template>
  2.   <web-view :src='url'
  3.     @loading='onLoading' @load='onLoad' @error='onError'></web-view>
  4. </template>
  5. <script setup lang='uts'>
  6. const url = ref('https://www.baidu.com')
  7. const onLoading = (event: UniWebViewLoadingEvent) => {
  8.   console.log('开始加载:', event.detail.src)
  9. }
  10. const onLoad = (event: UniWebViewLoadEvent) => {
  11.   console.log('加载完成:', event.detail.src)
  12. }
  13. const onError = (event: UniWebViewErrorEvent) => {
  14.   console.log('加载失败:', event.detail.errMsg)
  15.   console.log('错误码:', event.detail.errCode)
  16. }
  17. </script>
复制代码
原文列出的错误码为:100001 表示 SSL 错误,100002 表示页面错误,100003 表示 HTTP 错误。@error 的错误信息可能不够详细,建议结合 @loading 和 @load 一起判断加载状态。

三、本地 HTML 与路径规则
本地 HTML 只能访问 /static 目录下的文件,其他目录不会被打包,无法访问。示例:
  1. <web-view src='/static/web/index.html'></web-view>
复制代码
鸿蒙平台文件路径大小写敏感。本地 HTML 引用的资源路径必须与实际文件名大小写一致,建议在构建资源命名时统一规则。这个点对跨平台迁移尤其重要:在大小写不敏感的系统上能跑,在鸿蒙上可能直接变成资源找不到。

四、原生与 Web 通信
网页端通过 uni.postMessage 向原生应用发送消息,原生用 @message 接收:
  1. <template>
  2.   <web-view src='/static/web/bridge.html'
  3.     @message='onMessage'></web-view>
  4. </template>
  5. <script setup lang='uts'>
  6. const onMessage = (event: UniWebViewMessageEvent) => {
  7.   console.log('收到消息:', event.detail.data)
  8.   // data 是 UTSJSONObject[] 数组
  9. }
  10. </script>
复制代码
网页端发送:
  1. <!-- /static/web/bridge.html -->
  2. <script>
  3. uni.postMessage({
  4.   data: {
  5.     action: 'login',
  6.     token: 'xxx'
  7.   }
  8. })
  9. </script>
复制代码
这里有个容易踩的坑:@message 事件的 data 类型是 UTSJSONObject[] 数组,不是单个对象。网页端发送的数据会被包装成数组,解析时不要按单对象处理。

五、WebViewContext 控制导航
后退、前进、刷新、停止加载和获取当前 URL,需要通过 uni.createWebViewContext() 获取上下文对象,不能直接在 web-view 组件上设置:
  1. const webViewContext = uni.createWebViewContext('myWebView')
  2. webViewContext.back()
  3. webViewContext.forward()
  4. webViewContext.reload()
  5. webViewContext.stop()
  6. webViewContext.getWebViewUrl({
  7.   success: (res) => {
  8.     console.log('当前URL:', res.url)
  9.   }
  10. })
复制代码
如果要做带地址栏、前进后退按钮的浏览器式页面,App 平台可把输入框、web-view 和底部操作栏组合起来;Web/小程序平台则要接受全屏限制。

六、其他事件与鸿蒙原生对比
@download 可监听网页中的下载链接,事件里能拿到 url、contentLength、mimetype;@contentheightchange 可监听网页内容高度变化,拿到 height。自定义进度条样式可通过 :webview-styles 设置,例如 progress.color 为 #2196F3;设置 progress: false 可隐藏进度条。

鸿蒙原生开发中,网页使用 Web 组件:
  1. // 鸿蒙原生写法
  2. Web({ src: 'https://www.baidu.com', controller: this.controller })
  3.   .width('100%')
  4.   .height(300)
  5.   .javaScriptAccess(true)
  6.   .onPageEnd(() => {
  7.     console.log('加载完成')
  8.   })
复制代码
对比来看,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 完成,但错误处理、路径和平台滚动差异必须提前纳入测试。
回复

使用道具 举报

发表于 昨天 19:00 | 显示全部楼层

Re: 鸿蒙 uni-app x web-view 通信与嵌套滚动避坑

感谢分享,这些点整理得很细。鸿蒙上 uni-app x 的 web-view 在 Web/小程序是全屏且一个页面只能放一个,App 能自由调大小和位置,这个差异对做非全屏嵌入影响很大。嵌套滚动默认优先滚 web 内容,滚不动才交给外层,而且 Android 和 iOS 行为不同,确实得先在目标平台跑通外层容器滚动链路。 加载状态和错误处理也挺实用,100001、100002、100003 配合 @loading 和 @load 判断,比单看 @error 稳。本地 HTML 只能放 /static,鸿蒙路径大小写敏感,这个跨平台迁移时很容易踩,资源命名统一规则很关键。 通信部分提醒得很到位,@message 的 data 是 UTSJSONObject[] 数组,不是单对象,解析时按数组处理能避开一个大坑。WebViewContext 控制 back、forward、reload、stop、getWebViewUrl 也清楚了,不能直接挂组件上。整体收获很大,后面如果能把 android-nested-scroll 的实际配置和嵌套滚动验证结果再补一下就更好了。
回复 支持 反对

使用道具 举报

发表于 昨天 19:10 | 显示全部楼层

Re: 鸿蒙 uni-app x web-view 通信与嵌套滚动避坑

感谢整理,这些点对做鸿蒙混合开发挺实用。我印象最深的是 @message 的 data 是 UTSJSONObject[] 而不是单个对象,这个确实容易按常规思路写错;还有本地 HTML 只能访问 /static,加上鸿蒙路径大小写敏感,跨平台迁移时很可能出现明明文件在却加载不到的问题。嵌套滚动部分也提醒得很及时,鸿蒙默认优先滚 web 内容、滚不动再滚外层,但 Android 和 iOS 行为还有差异,看来只能以目标平台实测为准。加载状态和错误码那段也很清楚,@error 信息不够详细时结合 @loading、@load 判断状态比较稳。最后鸿蒙原生 Web 组件那段好像没写完,期待后续补全对比。
回复 支持 反对

使用道具 举报

发表于 昨天 19:20 | 显示全部楼层

Re: 鸿蒙 uni-app x web-view 通信与嵌套滚动避坑

看完很有收获,感谢楼主把鸿蒙上 uni-app x 的 web-view 讲得这么细。几个点我印象特别深:一是 Web 和小程序里的 web-view 是全屏且一个页面只能一个,App 才能自由调大小位置;二是嵌套滚动在鸿蒙默认优先滚网页内容,Android 和 iOS 还有差异,确实得先在目标平台把外层容器滚动链路跑一遍;三是本地 HTML 只能放 static 目录,而且鸿蒙路径大小写敏感,这个跨平台迁移时太容易中招了;四是 @message 收到的 data 是 UTSJSONObject 数组,不能按单对象解析。加载状态和错误码、WebViewContext 控制导航、下载和内容高度变化这些也都挺实用。想请教下,@error 的 100001、100002、100003 在实际排查时够用吗,还是更要靠 @loading 和 @load 的组合判断?另外本地资源命名统一大小写,你一般是怎么约定的?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-17 17:55 , Processed in 0.022075 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部