HarmonyOS Web 页面加载实战:用 Web 组件把“加载过程”这件事真正做好

HarmonyOS Web 页面加载实战:用 Web 组件把“加载过程”这件事真正做好

鸿蒙第四期开发者活动

很多人第一次用 HarmonyOS 的 Web 组件时,关注点都在“页面能不能打开”。
但项目一旦进入真实使用阶段,你会发现用户真正敏感的不是“能不能打开”,而是:

  • 点进去之后是不是立刻有反馈
  • 加载过程中会不会白一下、卡一下
  • 网络慢的时候,页面是不是像死了一样
  • 出错时有没有兜底和提示

官方这篇《Web 页面加载(Web Page Loading with Web Components)》讲的是机制,而我这篇想聊的是:

在真实项目里,你应该怎么“设计”一个 Web 页面加载过程。

不是 API 堆砌,而是体验导向。


一、先把核心事实说清楚:Web 页面加载是“多阶段”的

在 HarmonyOS 的 Web 组件里,一个页面的加载不是一次性完成的,而是至少经历这些阶段:

  1. 页面开始加载(请求已发出)
  2. 资源陆续加载中(HTML / CSS / JS / 图片)
  3. 加载进度变化
  4. 页面加载完成
  5. (异常情况)加载失败 / 渲染进程异常

官方把这些阶段通过一组事件暴露出来,比如:

  • onPageBegin
  • onProgressChange
  • onPageEnd
  • onRenderExited

理解这一点非常重要,因为:
你能不能把加载体验做好,取决于你有没有用好这些“时机点”。


二、最常见但体验最差的写法(很多人都这么写)

Web({
  src: 'https://example.com',
  controller: this.controller
})

这段代码没错,但问题是:

  • 页面开始加载时,UI 没任何变化
  • 网络慢的时候,用户看到的是一片空白
  • 加载失败时,没有任何提示

从用户视角看:像是点了没反应。


三、一个“及格线以上”的加载设计应该是什么样?

我自己在项目里总结了一套最低标准:

加载一开始就给反馈,加载中可感知进度,加载失败有兜底,加载完成再展示完整内容。

用 Web 组件的话,对应的就是:

  • onPageBegin → 打开 Loading
  • onProgressChange → 更新进度(可选)
  • onPageEnd → 关闭 Loading
  • onRenderExited → 显示错误页 / 重试

四、一个我真实项目里在用的“加载骨架”

1️⃣ ArkTS 页面结构思路

  • Web 始终存在
  • Loading 覆盖在 Web 上方
  • 加载完成后再隐藏 Loading

示例代码(核心逻辑)

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebLoadingPage {
  controller: webview.WebviewController = new webview.WebviewController();

  @State isLoading: boolean = true;
  @State progress: number = 0;

  build() {
    Stack() {
      // Web 页面
      Web({
        src: 'https://example.com',
        controller: this.controller
      })
        .onPageBegin(() => {
          this.isLoading = true;
          this.progress = 0;
        })
        .onProgressChange((value: number) => {
          this.progress = value;
        })
        .onPageEnd(() => {
          this.isLoading = false;
        })
        .onRenderExited(() => {
          this.isLoading = false;
          // 这里可以切到错误页
        })
        .width('100%')
        .height('100%')

      // Loading 覆盖层
      if (this.isLoading) {
        Column({ space: 12 }) {
          LoadingProgress()
          Text(`加载中 ${this.progress}%`)
            .fontSize(14)
            .opacity(0.7)
        }
        .width('100%')
        .height('100%')
        .backgroundColor('#FFFFFF')
        .justifyContent(FlexAlign.Center)
      }
    }
    .width('100%')
    .height('100%')
  }
}

这套写法的好处是:

  • 不会闪白(Web 还没渲染时,Loading 已经在)
  • 加载慢时,用户知道“还在加载”
  • 进度可选显示,不影响主流程

五、关于 onProgressChange:要不要用?

这是个很现实的问题。

我的建议是:

  • 普通业务页:可以不用,Loading + 文案就够
  • 内容页 / 重资源页:用进度条,体验会好很多
  • 协议页 / 轻页面:不用,反而显得多余

进度条不是必须,但“正在加载”的明确反馈是必须的


六、加载失败与异常:别假装它不会发生

很多人只写了 onPageBeginonPageEnd,但真实环境里:

  • 网络会断
  • DNS 会失败
  • Web 渲染进程可能异常退出

onRenderExited 就是专门给你兜底用的。

一个很实用的处理方式

.onRenderExited(() => {
  this.isLoading = false;
  this.showErrorPage = true;
})

然后给用户一个:

  • “加载失败”
  • “点击重试”
  • 或“返回上一页”

这比什么都不做要强太多。


七、我踩过的几个“加载相关的坑”

❌ 1)在 onPageEnd 里才显示页面内容

这样会导致:
Web 其实早就渲染好了,但你人为挡着不让看。

正确做法
Web 一直存在,Loading 是“盖上去的”。


❌ 2)用 Web 自己的 loading 样式

有些网页自己有 loading,但你等它加载出来才能看到,
那前面的白屏还是存在。

原生 Loading 永远比 Web loading 可靠。


❌ 3)页面切换时重复闪 loading

如果你在同一个 Web 页面里只是切 URL,可以考虑:

  • 判断是否真的需要重新 loading
  • 或只在“首次进入页面”显示全屏 loading

八、我现在对 Web 页面加载的整体策略

总结成几句话就是:

  1. 原生层负责加载反馈
  2. Web 只负责内容
  3. 所有慢与失败,都要有视觉回应
  4. 不让用户猜“是不是卡了”

九、写在最后的一句话(适合当博客结尾)

Web 页面加载不是一个 API 问题,而是一个体验设计问题。
当你愿意为“加载中的 1~3 秒”认真设计时,
用户对整个 App 的评价都会不一样。

posted @ 2025-12-18 16:28  骑老爷爷过马路  阅读(1)  评论(0)    收藏  举报