文章目录
-
- 大白话讲历史栈
- 流程图:后退逻辑
- 完整示例:按钮控制前进后退
- 跳转到指定历史位置:historyGo
- 实战:拦截物理返回键,优先执行 Web 后退
- 清除历史记录
- 常见误区
用户在 Web 组件里浏览了好几个页面,点了"返回"按钮——这个按钮到底该触发什么行为?是退出 App 还是回到上一个网页?这个问题搞不清楚,用户体验会很割裂。 本文把 ArkWeb 的历史导航 API 彻底讲清楚。
大白话讲历史栈
浏览器内部维护着一个"历史栈",每次跳转新页面就往栈里压一条记录。就像你在书上翻页,翻过的页留着记录,可以翻回去。
历史栈(从下往上):
[example.com] ← 最早
[example.com/page1]
[example.com/page2] ← 当前页
- backward():往栈下面走,相当于浏览器"←"按钮
- forward():往栈上面走,相当于浏览器"→"按钮
- accessBackward():检查能不能后退(栈下面还有没有记录)
- accessForward():检查能不能前进
流程图:后退逻辑

完整示例:按钮控制前进后退
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct HistoryNavPage {
controller: webview.WebviewController = new webview.WebviewController();
@State canGoBack: boolean = false;
@State canGoForward: boolean = false;
updateNavState() {
try {
this.canGoBack = this.controller.accessBackward();
this.canGoForward = this.controller.accessForward();
} catch (e) {
console.error('updateNavState error:', (e as BusinessError).message);
}
}
build() {
Column() {
Row({ space: 12 }) {
Button('← 后退')
.enabled(this.canGoBack)
.onClick(() => {
try {
if (this.controller.accessBackward()) {
this.controller.backward();
}
} catch (error) {
console.error(`backward error: ${(error as BusinessError).message}`);
}
})
Button('前进 →')
.enabled(this.canGoForward)
.onClick(() => {
try {
if (this.controller.accessForward()) {
this.controller.forward();
}
} catch (error) {
console.error(`forward error: ${(error as BusinessError).message}`);
}
})
Button('刷新')
.onClick(() => {
try {
this.controller.refresh();
} catch (error) {
console.error(`refresh error: ${(error as BusinessError).message}`);
}
})
}
.padding(8)
.width('100%')
Web({ src: 'https://www.example.com/cn/', controller: this.controller })
.onPageEnd(() => {
// 每次页面加载完成,重新检查导航状态
this.updateNavState();
})
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
}
}
跳转到指定历史位置:historyGo
除了一步步前进/后退,还可以直接跳到历史栈中的某个位置:
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct HistoryGoPage {
controller: webview.WebviewController = new webview.WebviewController();
build() {
Column() {
Row({ space: 10 }) {
Button('后退2步')
.onClick(() => {
try {
// 负数 = 后退,正数 = 前进,0 = 刷新当前页
this.controller.historyGo(–2);
} catch (error) {
console.error(`historyGo error: ${(error as BusinessError).message}`);
}
})
Button('前进1步')
.onClick(() => {
try {
this.controller.historyGo(1);
} catch (error) {
console.error(`historyGo error: ${(error as BusinessError).message}`);
}
})
}
Web({ src: 'https://www.example.com', controller: this.controller })
.width('100%')
.layoutWeight(1)
}
}
}
historyGo(steps) 参数说明:
- historyGo(-1) 等价于 backward()
- historyGo(1) 等价于 forward()
- historyGo(0) 刷新当前页
- 超出历史栈范围时,什么都不做
实战:拦截物理返回键,优先执行 Web 后退
手机上按物理返回键,默认会退出当前 Ability。但如果 Web 还有历史记录,应该先让 Web 后退:
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct BackKeyInterceptPage {
controller: webview.WebviewController = new webview.WebviewController();
build() {
Column() {
Web({ src: 'https://www.example.com', controller: this.controller })
.width('100%')
.height('100%')
}
.onBackPress(() => {
if (this.controller.accessBackward()) {
// Web 有历史记录,先让 Web 后退
this.controller.backward();
return true; // true = 已处理,不再执行默认返回
}
// Web 没有历史了,执行默认返回(退出页面)
return false;
})
}
}
这个模式是最常见的 Web 容器返回处理方案,强烈推荐。
清除历史记录
登录后跳转首页,不允许用户退回登录页的场景:
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct ClearHistoryPage {
controller: webview.WebviewController = new webview.WebviewController();
build() {
Column() {
Button('登录成功,跳转首页')
.onClick(() => {
try {
this.controller.loadUrl('https://www.example.com/home');
// 清除所有浏览历史,防止用户后退到登录页
this.controller.clearHistory();
} catch (error) {
console.error(`error: ${(error as BusinessError).message}`);
}
})
Web({ src: 'https://www.example.com/login', controller: this.controller })
.width('100%')
.layoutWeight(1)
}
}
}
常见误区
误区1:直接调 backward() 不判断 accessBackward() 没有历史记录时调 backward() 不会报错,但什么都不发生。养成习惯先 access 再操作。
误区2:修改 src 属性来切换页面 Web 组件的 src 是初始值,组件创建后修改它不会触发重新加载。要切换页面必须用 controller.loadUrl()。
误区3:以为 refresh() 会清空历史 刷新只是重新加载当前页,历史栈不变。






