HarmonyOS7 网页地址切换怎么做:WebUrlLoadingFlow 讲透 URL 加载流程
文章目录

前言
把 Web 组件放进页面,只是第一步。真正到了业务里,页面几乎不可能永远只加载一个固定地址。活动页会切换链接,帮助中心会跳不同文档,调试阶段也经常要在多个测试地址之间来回切。

所以这篇更重要的,不是“加载网页”本身,而是 URL 切换时的状态管理。什么时候开始加载,进度怎么显示,按钮点完后页面怎么反馈,这些细节不处理,用户会觉得页面是卡住了,不是正在加载。
这个案例的核心能力
案例设计得很直接:一边维护当前 URL,一边模拟加载进度,再提供几个快捷按钮切换地址。它实际上是在讲一套最小网页加载流程。
里面最值得关注的是三个状态:
currentUrl:当前要加载的网页地址loadProgress:当前进度isLoading:是否处于加载中
有了这三个状态,页面就能把“我现在正在打开哪个地址”和“它到底加载到哪一步了”表达出来。
完整代码
import { DEMO_BG_COLOR, DEMO_CARD_COLOR, DEMO_THEME_COLOR, DEMO_SUBTEXT_COLOR } from './types'
@Entry
@Component
struct WebUrlLoadingFlow {
@State isShow: boolean = true
@State currentUrl: string = 'https://www.example.com'
@State loadProgress: number = 0
@State isLoading: boolean = false
loadUrl(url: string): void {
this.currentUrl = url
this.isLoading = true
this.loadProgress = 0
const timer = setInterval(() => {
if (this.loadProgress < 100) {
this.loadProgress += 10
} else {
this.isLoading = false
clearInterval(timer)
}
}, 200)
}
build() {
Column() {
if (this.isShow) {
Scroll() {
Column({ space: 16 }) {
Text('Web 加载 URL').fontSize(16).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)
Column() {
Row() {
Text('当前: ').fontSize(12).fontColor('#666666')
Text(this.currentUrl).fontSize(12).fontColor(DEMO_THEME_COLOR).maxLines(1)
}.margin({ bottom: 8 })
if (this.isLoading) {
Progress({ value: this.loadProgress, total: 100, type: ProgressType.Linear })
.width('100%')
.color(DEMO_THEME_COLOR)
}
Column() {
Text('Web View').fontSize(16).fontColor('#FFFFFF')
Text(this.currentUrl).fontSize(11).fontColor('#FFFFFF80').margin({ top: 4 })
}
.width('100%')
.height(180)
.backgroundColor('#444444')
.borderRadius(10)
.justifyContent(FlexAlign.Center)
}
.backgroundColor(DEMO_CARD_COLOR)
.padding(12)
.borderRadius(12)
Column() {
Text('快捷切换 URL').fontSize(13).fontColor('#4D96FF').margin({ bottom: 8 })
Row({ space: 6 }) {
Button('百度')
.onClick(() => { this.loadUrl('https://www.baidu.com') })
.fontSize(12)
.backgroundColor('#4D96FF')
Button('腾讯')
.onClick(() => { this.loadUrl('https://www.tencent.com') })
.fontSize(12)
.backgroundColor('#6BCB77')
Button('本地')
.onClick(() => { this.loadUrl('about:blank') })
.fontSize(12)
.backgroundColor('#FFA500')
}.width('100%').justifyContent(FlexAlign.SpaceEvenly)
}
.backgroundColor('#E8F4FD')
.padding(12)
.borderRadius(12)
Column({ space: 6 }) {
Text('URL 加载说明').fontSize(14).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)
Text('支持 https:// http:// 网络协议').fontSize(12).fontColor('#333333')
Text('支持加载本地 HTML 文件').fontSize(12).fontColor('#333333')
Text('.onPageBegin/onPageEnd 监听加载状态').fontSize(12).fontColor('#333333')
Text('.onProgressChange 获取加载百分比').fontSize(12).fontColor('#333333')
Text('WebController 提供前进/后退/刷新方法').fontSize(12).fontColor('#333333')
}
.width('100%')
.backgroundColor('#F0F0FF')
.padding(14)
.borderRadius(12)
}
.width('100%')
}
}
Text('WebUrlLoadingFlow - 加载不同网页地址')
.fontSize(12)
.fontColor(DEMO_SUBTEXT_COLOR)
.margin({ top: 12 })
}
.width('100%')
.height('100%')
.backgroundColor(DEMO_BG_COLOR)
.padding(16)
}
}

loadUrl() 这个方法为什么是全篇重点
这个案例最核心的代码,其实就这一段:
loadUrl(url: string): void {
this.currentUrl = url
this.isLoading = true
this.loadProgress = 0
const timer = setInterval(() => {
if (this.loadProgress < 100) {
this.loadProgress += 10
} else {
this.isLoading = false
clearInterval(timer)
}
}, 200)
}
你可以把它理解成一次完整的“网页切换事务”。
先更新地址,再告诉页面“我要开始加载了”,然后把旧进度清零,最后通过定时器模拟新的加载过程。虽然这里不是实际的 Web 回调,但状态切换逻辑已经搭好了。
真实项目里,你完全可以把 setInterval 这套模拟逻辑,换成 onPageBegin、onProgressChange 和 onPageEnd 驱动。
为什么要把地址显示出来
案例顶部有一行很朴素的当前地址展示:
Row() {
Text('当前: ')
Text(this.currentUrl).maxLines(1)
}
这一行看起来不复杂,但在调试和运维页面里特别有用。
因为 Web 内容是黑盒感很强的区域,你如果不把当前地址显式展示出来,切换失败时很难第一时间判断是路由没变、状态没更新,还是网页本身打不开。
尤其做内部工具、配置后台、嵌套调试页时,这种“把上下文直接给出来”的做法,能省很多排查时间。
进度条为什么值得单独做
很多 Web 容器页的问题,不是慢,而是“用户不知道它是不是还活着”。
案例在 isLoading 为 true 时显示进度条:
if (this.isLoading) {
Progress({ value: this.loadProgress, total: 100, type: ProgressType.Linear })
.width('100%')
.color(DEMO_THEME_COLOR)
}
这类加载反馈最重要的价值,不是告诉用户精确百分比,而是告诉用户:页面在处理,不是没反应。
如果你后面接的是实际 Web 组件,这块完全可以绑定 onProgressChange 回传的数据。只要用户看到进度在动,耐心就会多很多。
按钮切换 URL 的结构为什么好用
案例用了三个按钮模拟不同来源:
Button('百度').onClick(() => { this.loadUrl('https://www.baidu.com') })
Button('腾讯').onClick(() => { this.loadUrl('https://www.tencent.com') })
Button('本地').onClick(() => { this.loadUrl('about:blank') })
这个写法其实非常适合你在开发期快速验证 Web 页面行为。比如:
- 外网地址能不能正常打开
- 不同域名切换时状态有没有残留
- 空白页、本地页、异常页时加载态是否正常收口
尤其最后这个 about:blank,虽然只是空白页,但很适合测试切换逻辑是不是稳定。
关键代码怎么迁移到真实 Web 组件
如果你要把这个案例真正变成可运行网页容器,思路很简单。
第一步,定义 WebController。
第二步,把中间占位区域换成真正的 Web({ src, controller })。
第三步,用加载回调接管模拟定时器:
onPageBegin时设置isLoading = trueonProgressChange时更新loadProgressonPageEnd时设置isLoading = falseonErrorReceive时关闭加载态并提示错误
也就是说,这个案例讲的不是“假数据页面”,而是一套你后面能直接换成真逻辑的页面框架。
这类页面最常见的坑
第一个坑,是重复点击切换按钮时没有处理前一个加载流程。结果进度条和地址状态打架,页面会出现错乱。
第二个坑,是加载失败后忘了把 isLoading 关掉。用户看到的就是一根永远不结束的进度条。
第三个坑,是 URL 太长又没有做 maxLines(1),界面会被地址撑坏。
第四个坑,是只考虑线上地址,不考虑本地页和空白页调试。实际开发阶段,这两种地址非常有用。
这个案例适合用在哪些业务里
协议页、帮助中心、运营落地页、嵌套控制台、企业内部混合页面,都很适合用这套结构。
尤其当你需要“在一个原生壳子里切不同网页内容”时,状态和反馈比视觉更重要。因为用户点完按钮后,第一需求从来不是炫酷,而是确定系统在响应。
写在最后
网页切换这件事,表面看只是改一个 src,实际做得稳不稳,全看你有没有把状态流理顺。地址、加载中、进度,这三个状态处理好,用户体验就不会差到哪里去。
等你把这套流程跑顺,再往后做前进、后退、刷新,甚至做 JS 桥接,思路都会清楚很多。
更多推荐



所有评论(0)