ArkWeb实战学习笔记03-页面加载与导航控制

1. 开篇

开发混合应用时,ArkWeb组件是鸿蒙应用中嵌入Web能力的核心入口。实际开发中常遇到以下问题:URL加载后白屏、本地HTML资源路径错误导致404、编程控制前进/后退无效、页面加载进度不刷新、网络异常时无反馈。本篇直接围绕这些场景,解析URL与本地HTML资源的加载方法、前进/后退/刷新的编程控制、加载进度监听与错误处理三个基础实现,并给出关键注意事项。

2. 核心概念

ArkWeb属于Ability Kit(程序框架服务)下的应用框架Kit。其加载能力基于声明式UI组件Web,通过系统封装的接口完成页面渲染与导航控制。HarmonyOS SDK从API 11开始以Kit维度提供开放能力,ArkWeb作为应用框架Kit的一部分,接口需通过import方式导入使用。

导航控制中的“前进”与“后退”依赖浏览器引擎内部的页面历史栈;“刷新”则触发当前页面的重新加载。加载进度监听通过onProgressChange回调实时反馈,错误处理则通过onErrorReceive捕获加载失败事件。理解这些机制有助于排查白屏、导航失效等问题。

3. 核心实现

以下代码基于DevEco Studio 6.0.0及以上版本HarmonyOS SDK 6.0.0(20)及以上版本环境测试。所有接口均来自ArkWeb官方文档。

3.1 加载URL与本地HTML资源

加载远程URL或本地rawfile下的HTML文件,通过设置Web组件的src属性完成。本地资源必须放在resources/rawfile目录下,且路径以$rawfile()方式引用。

// 加载远程URL
Web({ src: 'https://www.harmonyos.com', controller: new webview.WebviewController() })

// 加载本地rawfile下的HTML
Web({ src: $rawfile('local.html'), controller: new webview.WebviewController() })

注意事项:

  • 本地HTML文件内引用的CSS、JS资源也需要放在rawfile目录或其子目录下,且路径需使用相对路径(相对于HTML文件所在目录),否则资源加载会失败。
  • 如果HTML中使用了外部网络资源(如CDN图片),应用需申请网络权限(ohos.permission.INTERNET),否则网络资源无法加载。

3.2 前进/后退/刷新导航控制

除了用户手势触发的前进/后退,开发者常需通过按钮编程控制。使用WebviewController实例的forward()backward()refresh()方法前,应通过accessForward()accessBackward()检查历史栈是否存在可操作记录,避免无操作时调用导致无响应。

在这里插入图片描述

@Entry
@Component
struct WebPage {
  controller: webview.WebviewController = new webview.WebviewController()
  // 不直接使用布尔值响应式绑定,而是每次点击时检查
  build() {
    Column() {
      Web({ src: 'https://example.com', controller: this.controller })
      Row() {
        Button('后退').onClick(() => {
          if (this.controller.accessBackward()) {
            this.controller.backward()
          } else {
            console.warn('无法后退:无历史记录')
          }
        })
        Button('刷新').onClick(() => {
          this.controller.refresh()
        })
        Button('前进').onClick(() => {
          if (this.controller.accessForward()) {
            this.controller.forward()
          } else {
            console.warn('无法前进:无历史记录')
          }
        })
      }
    }
  }
}

注意事项:

  • backward()forward()不会触发页面重载,只改变当前展示的页面历史快照。如果在Web页面内执行了重定向或hash路由变化,历史栈可能不按预期工作,建议在onUrlLoadIntercept中自行管理路由。
  • 刷新可能引起页面闪烁或重新执行脚本,对于填写表单的页面需提示用户可能丢失未保存数据。

3.3 加载进度监听与错误处理

实时获取加载进度(0-100)通过onProgressChange回调。错误处理通过onErrorReceive捕获加载失败事件,回调参数为ErrorReceive对象,包含错误码(errorCode)和错误描述(description)。注意onErrorReceive可能因资源重试或子资源加载而多次触发,需避免重复弹窗或日志堆积。

@Entry
@Component
struct WebPage {
  controller: webview.WebviewController = new webview.WebviewController()
  @State progress: number = 0
  @State errorMsg: string = ''

  build() {
    Column() {
      // 进度条
      if (this.progress < 100) {
        Progress({ value: this.progress, total: 100 }).width('100%')
      }
      Web({ src: 'https://example.com', controller: this.controller })
        .onProgressChange((event) => {
          this.progress = event.newProgress
        })
        .onErrorReceive((event) => {
          // 避免多次弹窗,用标志位控制
          if (this.errorMsg === '') {
            this.errorMsg = `加载失败:${event.error.description} (错误码: ${event.error.errorCode})`
            console.error(this.errorMsg)
            // 可在此显示Toast或对话框
          }
        })
    }
  }
}

注意事项:

  • onProgressChange不会在加载完成时自动移除进度条,需判断newProgress === 100后隐藏进度UI。
  • onErrorReceive的错误码定义请查阅ArkWeb错误码表(如-1: 未知错误,-6: 网络不可达)。对于跨域资源加载失败(错误码-8),通常由CORS配置引起,前端无法通过回调解决。
  • 如果只需监听主页面加载失败,可在onErrorReceive中检查event.request.isMainFrame(当前框架不支持,需等API更新),或者利用onPageEndonPageBegin结合计时器判断超时。

关于页面加载的性能优化,比如本地资源预加载、缓存策略复用,你在实践中是如何处理的?

3.3 加载进度监听与错误处理

页面加载体验中,实时展示进度、异常时给出错误提示是常见需求。ArkWeb通过 onProgressChangeonErrorReceive 两个回调即可实现。

onProgressChange 返回 { newProgress: number },数值为 0~100 的整数,对应页面加载百分比。onErrorReceive 在页面完全加载失败时触发,回调参数包含 errorCodedescription

Web({ src: 'https://example.com', controller: this.controller })
  .onProgressChange((event) => {
    console.info('加载进度:' + event.newProgress + '%')
  })
  .onErrorReceive((event) => {
    // event.errorCode 和 event.description 提供错误详情
    console.error('加载失败,错误码:' + event.errorCode + ',描述:' + event.description)
  })

在这里插入图片描述

实用提示

  • 进度值不一定是严格递增的,某些页面可能因重定向、懒加载导致进度回退或跳变,建议仅用于进度条显示,不要依赖它判断“加载完成”。
  • onErrorReceive 仅在页面主文档加载失败时触发。如果只有图片、CSS 等子资源失败,主文档成功加载,则不会触发此回调。需要捕获资源级错误时,应额外使用 onHttpErrorReceiveonResourceLoadError

4. 注意事项

  • 所有 ArkWeb API 均需先导入模块。导入语句请以当前 SDK 版本为准,API 12+ 的推荐写法为 import { webview } from '@kit.ArkWeb';
  • 使用 backward()forward() 前,优先调用 accessBackward()accessForward() 检查是否有历史记录,避免走空。
  • 本地资源加载时,文件必须放在 resources/rawfile 目录下,src 使用 $rawfile('文件名.html') 格式,不支持子目录嵌套。

5. 常见问题 FAQ

Q1: 如何判断是否可以执行后退/前进?
A: 调用 webviewController.accessBackward()accessForward(),返回布尔值。

Q2: 加载本地HTML时出现白屏?
A: 确认文件在 resources/rawfile 目录下,且 src 中的文件名、扩展名与资源文件完全一致。注意大小写也要匹配。

Q3: onErrorReceive 回调不触发?
A: 该回调只在网页整体加载失败时触发。如果只是部分资源失败(如一张图片),主文档加载成功,不会触发此回调。可配合 onHttpErrorReceive 捕获资源级错误。


你在实际开发中还遇到过哪些加载异常场景?欢迎在评论区补充。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐