HarmonyOS Web 页面加载实战:用 Web 组件把“加载过程”这件事真正做好
HarmonyOS Web 页面加载实战:用 Web 组件把“加载过程”这件事真正做好
很多人第一次用 HarmonyOS 的 Web 组件时,关注点都在“页面能不能打开”。
但项目一旦进入真实使用阶段,你会发现用户真正敏感的不是“能不能打开”,而是:
- 点进去之后是不是立刻有反馈
- 加载过程中会不会白一下、卡一下
- 网络慢的时候,页面是不是像死了一样
- 出错时有没有兜底和提示
官方这篇《Web 页面加载(Web Page Loading with Web Components)》讲的是机制,而我这篇想聊的是:
在真实项目里,你应该怎么“设计”一个 Web 页面加载过程。
不是 API 堆砌,而是体验导向。
一、先把核心事实说清楚:Web 页面加载是“多阶段”的
在 HarmonyOS 的 Web 组件里,一个页面的加载不是一次性完成的,而是至少经历这些阶段:
- 页面开始加载(请求已发出)
- 资源陆续加载中(HTML / CSS / JS / 图片)
- 加载进度变化
- 页面加载完成
- (异常情况)加载失败 / 渲染进程异常
官方把这些阶段通过一组事件暴露出来,比如:
onPageBeginonProgressChangeonPageEndonRenderExited
理解这一点非常重要,因为:
你能不能把加载体验做好,取决于你有没有用好这些“时机点”。
二、最常见但体验最差的写法(很多人都这么写)
Web({
src: 'https://example.com',
controller: this.controller
})
这段代码没错,但问题是:
- 页面开始加载时,UI 没任何变化
- 网络慢的时候,用户看到的是一片空白
- 加载失败时,没有任何提示
从用户视角看:像是点了没反应。
三、一个“及格线以上”的加载设计应该是什么样?
我自己在项目里总结了一套最低标准:
加载一开始就给反馈,加载中可感知进度,加载失败有兜底,加载完成再展示完整内容。
用 Web 组件的话,对应的就是:
onPageBegin→ 打开 LoadingonProgressChange→ 更新进度(可选)onPageEnd→ 关闭 LoadingonRenderExited→ 显示错误页 / 重试
四、一个我真实项目里在用的“加载骨架”
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 + 文案就够
- 内容页 / 重资源页:用进度条,体验会好很多
- 协议页 / 轻页面:不用,反而显得多余
进度条不是必须,但“正在加载”的明确反馈是必须的。
六、加载失败与异常:别假装它不会发生
很多人只写了 onPageBegin 和 onPageEnd,但真实环境里:
- 网络会断
- 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 页面加载的整体策略
总结成几句话就是:
- 原生层负责加载反馈
- Web 只负责内容
- 所有慢与失败,都要有视觉回应
- 不让用户猜“是不是卡了”
九、写在最后的一句话(适合当博客结尾)
Web 页面加载不是一个 API 问题,而是一个体验设计问题。
当你愿意为“加载中的 1~3 秒”认真设计时,
用户对整个 App 的评价都会不一样。

浙公网安备 33010602011771号