HarmonyOS鸿蒙Next中应用页面跳转和参数传递怎么实现
HarmonyOS鸿蒙Next中应用页面跳转和参数传递怎么实现 应用需要页面跳转和参数传递:
- 点击按钮跳转到详情页
- 携带参数跳转
- 返回时传递结果
- 路由拦截和鉴权
页面跳转
NavPathStack通过Push相关的接口(如pushPath、pushPathByName、pushDestination、pushDestinationByName)去实现页面跳转的功能,主要分为以下三类:
- 普通跳转,通过页面的name去跳转,并可以携带param。
this.pageStack.pushPath({ name: "PageOne", param: "PageOne Param" });
this.pageStack.pushPathByName("PageOne", "PageOne Param");
- 带返回回调的跳转,跳转时添加onPop回调,能在页面出栈时获取返回信息,并进行处理。
this.pageStack.pushPathByName('PageOne', "PageOne Param", (popInfo) => {
console.info('Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result));
});
- 带错误码的跳转,跳转结束会触发异步回调,返回错误码信息。
this.pageStack.pushDestination({name: "PageOne", param: "PageOne Param"})
.catch((error: BusinessError) => {
console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
}).then(() => {
console.info('Push destination succeed.');
});
this.pageStack.pushDestinationByName("PageOne", "PageOne Param")
.catch((error: BusinessError) => {
console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
}).then(() => {
console.info('Push destination succeed.');
});
页面返回
NavPathStack通过pop相关接口(如pop、popToName、popToIndex、clear)去实现页面返回功能。
// 返回到上一页
this.pageStack.pop();
// 返回到上一个PageOne页面
this.pageStack.popToName("PageOne");
// 返回到索引为1的页面
this.pageStack.popToIndex(1);
// 返回到根首页(清除栈中所有页面)
this.pageStack.clear();
参数获取
NavDestination子页第一次创建时会触发onReady回调,可以获取此页面对应的参数。
@Component
struct Page01 {
pathStack: NavPathStack | undefined = undefined;
pageParam: string = '';
build() {
NavDestination() {
// ...
}.title('Page01')
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack;
this.pageParam = context.pathInfo.param as string;
})
}
}
NavDestination组件中可以通过设置onResult接口,接收返回时传递的路由参数。
class NavParam {
desc: string = 'navigation-param'
}
@Component
struct DemoNavDestination {
// ...
build() {
NavDestination() {
// ...
}
.onResult((param: Object) => {
if (param instanceof NavParam) {
console.info('TestTag', 'get NavParam, its desc: ' + (param as NavParam).desc);
return;
}
console.info('TestTag', 'param not instance of NavParam');
})
}
}
其他业务场景,可以通过主动调用NavPathStack的Get相关接口(如getAllPathName、getParamByIndex、getParamByName、getIndexByName)去获取指定页面的参数。
// 获取栈中所有页面name集合
this.pageStack.getAllPathName();
// 获取索引为1的页面参数
this.pageStack.getParamByIndex(1);
// 获取PageOne页面的参数
this.pageStack.getParamByName("PageOne");
// 获取PageOne页面的索引集合
this.pageStack.getIndexByName("PageOne");
路由拦截
NavPathStack提供了setInterception方法,用于设置Navigation页面跳转拦截回调。该方法需要传入一个NavigationInterception对象,该对象包含三个回调函数:
| 名称 | 描述 |
|---|---|
| willShow | 页面跳转前回调,允许操作栈,在当前跳转生效。 |
| didShow | 页面跳转后回调,在该回调中操作栈会在下一次跳转生效。 |
| modeChange | Navigation单双栏显示状态发生变更时触发该回调。 |
开发者可以在willShow回调中通过修改路由栈来实现路由拦截重定向的能力。
this.pageStack.setInterception({
willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
operation: NavigationOperation, animated: boolean) => {
if (typeof to === "string") {
console.info("target page is navigation home page.");
return;
}
// 将跳转到PageTwo的路由重定向到PageOne
let target: NavDestinationContext = to as NavDestinationContext;
if (target.pathInfo.name === 'PageTwo') {
target.pathStack.pop();
target.pathStack.pushPathByName('PageOne', null);
}
}
})
更多关于HarmonyOS鸿蒙Next中应用页面跳转和参数传递怎么实现的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
666
解决方案
1. 基础路由跳转
import { router } from '@kit.ArkUI';
@Entry
@Component
struct HomePage {
build() {
Column({ space: 16 }) {
// ✅ 方式1: pushUrl跳转(可返回)
Button('查看详情')
.onClick(() => {
router.pushUrl({
url: 'pages/DetailPage'
});
})
// ✅ 方式2: replaceUrl跳转(不可返回)
Button('登录')
.onClick(() => {
router.replaceUrl({
url: 'pages/LoginPage'
});
})
// ✅ 方式3: back返回
Button('返回')
.onClick(() => {
router.back();
})
}
}
}
2. 携带参数跳转
// 发送页面
@Component
struct ItemList {
onItemClick(item: Item): void {
// ✅ 通过params传递参数
router.pushUrl({
url: 'pages/ItemDetailPage',
params: {
itemId: item.id,
itemName: item.name,
// ✅ 可以传递对象
itemData: item
}
}, router.RouterMode.Standard);
}
build() {
List() {
ForEach(this.items, (item: Item) => {
ListItem() {
Text(item.name)
}
.onClick(() => {
this.onItemClick(item);
})
})
}
}
}
// 接收页面
@Entry
@Component
struct ItemDetailPage {
@State itemId: number = 0;
@State itemName: string = '';
@State itemData: Item | null = null;
aboutToAppear(): void {
// ✅ 获取路由参数
const params = router.getParams() as Record<string, Object>;
this.itemId = params.itemId as number;
this.itemName = params.itemName as string;
this.itemData = params.itemData as Item;
console.info('接收参数:', this.itemId, this.itemName);
}
build() {
Column() {
Text(`ID: ${this.itemId}`)
Text(`名称: ${this.itemName}`)
}
}
}
3. 返回并传递结果
// 页面A: 打开页面B
@Component
struct PageA {
@State selectedValue: string = '';
async openSelector(): Promise<void> {
// ✅ 打开选择器页面
await router.pushUrl({
url: 'pages/SelectorPage'
});
// ✅ 监听返回结果
router.getParams(); // 获取返回的数据
}
aboutToAppear(): void {
// ✅ 页面重新显示时获取结果
const params = router.getParams() as Record<string, Object>;
if (params && params.selectedValue) {
this.selectedValue = params.selectedValue as string;
}
}
}
// 页面B: 选择后返回
@Component
struct SelectorPage {
onSelect(value: string): void {
// ✅ 返回并携带数据
router.back({
url: 'pages/PageA',
params: {
selectedValue: value
}
});
}
build() {
List() {
ListItem() {
Text('选项1')
}
.onClick(() => {
this.onSelect('选项1');
})
}
}
}
4. RouterMode模式
// ✅ Standard模式(默认): 每次都创建新实例
router.pushUrl({
url: 'pages/DetailPage'
}, router.RouterMode.Standard);
// ✅ Single模式: 复用已有实例
router.pushUrl({
url: 'pages/DetailPage',
params: { id: 2 }
}, router.RouterMode.Single);
// 如果DetailPage已存在,会复用并更新参数
5. 路由拦截
/**
* 路由守卫
*/
export class RouterGuard {
/**
* 需要登录的页面
*/
private static authPages: string[] = [
'pages/ProfilePage',
'pages/SettingsPage',
'pages/OrderPage'
];
/**
* 跳转前检查
*/
static async navigate(url: string, params?: Object): Promise<void> {
// ✅ 检查是否需要登录
if (this.authPages.includes(url)) {
const isLoggedIn = await this.checkLogin();
if (!isLoggedIn) {
// 未登录,跳转到登录页
router.pushUrl({
url: 'pages/LoginPage',
params: {
redirect: url, // 登录后跳转回来
redirectParams: params
}
});
return;
}
}
// 已登录或不需要登录,正常跳转
router.pushUrl({ url, params });
}
private static async checkLogin(): Promise<boolean> {
const token = await AppSettings.getInstance().getUserToken();
return token !== null && token !== '';
}
}
// 使用路由守卫
Button('我的订单')
.onClick(() => {
RouterGuard.navigate('pages/OrderPage');
})
6. 路由工具类
/**
* 路由工具类
*/
export class RouterUtils {
/**
* 跳转到详情页
*/
static goToDetail(id: number): void {
router.pushUrl({
url: 'pages/DetailPage',
params: { id }
});
}
/**
* 跳转到编辑页
*/
static goToEdit(item: Item): void {
router.pushUrl({
url: 'pages/EditPage',
params: { item: JSON.stringify(item) } // ✅ 复杂对象转JSON
});
}
/**
* 安全返回(检查是否有上一页)
*/
static safeBack(): void {
const length = router.getLength();
if (length > 1) {
router.back();
} else {
// 没有上一页,跳转到首页
router.replaceUrl({ url: 'pages/Index' });
}
}
/**
* 清空路由栈并跳转
*/
static clearAndGo(url: string): void {
router.clear(); // ✅ 清空路由栈
router.pushUrl({ url });
}
/**
* 获取参数(类型安全)
*/
static getParams<T>(): T | null {
const params = router.getParams();
return params ? params as T : null;
}
}
// 使用
RouterUtils.goToDetail(123);
RouterUtils.goToEdit(item);
RouterUtils.safeBack();
关键API
1. 路由跳转
| 方法 | 说明 | 是否可返回 |
|---|---|---|
| pushUrl | 跳转到新页面 | ✅ |
| replaceUrl | 替换当前页面 | ❌ |
| back | 返回上一页 | - |
| clear | 清空路由栈 | - |
2. 获取信息
// ✅ 获取路由参数
const params = router.getParams();
// ✅ 获取路由栈长度
const length = router.getLength();
// ✅ 获取当前路由状态
const state = router.getState();
console.info('当前页面:', state.path);
console.info('路由名称:', state.name);
实战案例
案例1: 列表-详情跳转
// 列表页
@Component
struct ItemList {
@State items: Item[] = [];
build() {
List() {
ForEach(this.items, (item: Item) => {
ListItem() {
Row() {
Text(item.name).fontSize(16);
}
.width('100%')
.padding(16)
}
.onClick(() => {
// ✅ 跳转到详情
router.pushUrl({
url: 'pages/ItemDetailPage',
params: { itemId: item.id }
});
})
})
}
}
}
// 详情页
@Entry
@Component
struct ItemDetailPage {
@State item: Item | null = null;
private itemId: number = 0;
aboutToAppear(): void {
// ✅ 获取参数
const params = router.getParams() as Record<string, Object>;
this.itemId = params.itemId as number;
// 加载详情
this.loadDetail();
}
async loadDetail(): Promise<void> {
this.item = await ItemDao.findById(this.itemId);
}
build() {
Column() {
// 返回按钮
Row() {
Image($r('app.media.ic_back'))
.width(24)
.height(24)
.onClick(() => {
router.back();
})
}
if (this.item) {
Text(this.item.name).fontSize(20);
}
}
}
}
案例2: 登录后跳转回原页面
// 登录页
@Entry
@Component
struct LoginPage {
private redirectUrl: string = '';
aboutToAppear(): void {
const params = router.getParams() as Record<string, Object>;
this.redirectUrl = params?.redirect as string || 'pages/Index';
}
async onLogin(): Promise<void> {
// 登录成功
await login();
// ✅ 跳转回原页面
router.replaceUrl({
url: this.redirectUrl
});
}
}
最佳实践
1. 参数传递
// ✅ 推荐:传递ID,详情页加载数据
router.pushUrl({
url: 'pages/DetailPage',
params: { id: 123 } // 只传ID
});
// ❌ 不推荐:传递大对象
router.pushUrl({
url: 'pages/DetailPage',
params: { item: largeObject } // 对象太大
});
2. 错误处理
try {
await router.pushUrl({ url: 'pages/DetailPage' });
} catch (err) {
console.error('跳转失败:', err);
promptAction.showToast({ message: '页面不存在' });
}
3. 生命周期
@Entry
@Component
struct MyPage {
// ✅ 页面首次创建
aboutToAppear(): void {
const params = router.getParams();
// 初始化数据
}
// ✅ 页面重新显示(从其他页面返回时)
onPageShow(): void {
// 刷新数据
this.refreshData();
}
// ✅ 页面隐藏(跳转到其他页面时)
onPageHide(): void {
// 保存状态
}
}
常见问题
Q1: 返回时如何传递数据?
使用router.back()的params参数,在上一页通过getParams获取。
Q2: 如何清空路由栈?
使用router.clear()清空,然后pushUrl跳转。
Q3: 如何实现Tab内导航?
使用Navigation组件,而不是router。
总结
路由导航要点:
✅ pushUrl跳转,back返回 ✅ params传递参数 ✅ RouterMode控制实例 ✅ 路由守卫鉴权 ✅ 工具类封装常用跳转
参考资料
在HarmonyOS Next中,页面跳转通过router.pushUrl()实现。参数传递使用router.pushUrl()的params选项,参数以键值对形式传递。目标页面通过router.getParams()获取传递的参数。
在HarmonyOS Next中,页面跳转与参数传递主要通过router模块实现,以下是核心实现方式:
1. 基础页面跳转与参数传递
- 跳转:使用
router.pushUrl()方法,指定目标页面的pages路径。 - 传递参数:通过
router.pushUrl()的params属性携带键值对参数。
// 从Index页面跳转到Detail页面,并传递id参数
import { router } from '@kit.ArkUI';
router.pushUrl({
url: 'pages/Detail',
params: { id: 123 }
})
2. 目标页面接收参数
在目标页面的aboutToAppear()生命周期或使用@State装饰器接收参数:
// Detail.ets
@State id: number = 0;
aboutToAppear() {
const params = router.getParams() as Record<string, number>;
this.id = params['id'];
}
3. 返回上一页并传递结果
- 返回:使用
router.back()方法。 - 传递结果:通过
router.back()的params属性携带返回数据。
// 从Detail页面返回Index页面,并传递结果
router.back({
url: 'pages/Index',
params: { result: 'success' }
});
在Index页面的aboutToAppear()中可通过router.getParams()接收返回参数。
4. 路由拦截与鉴权
通过router.addInterceptor()实现全局路由拦截:
// 在EntryAbility的onWindowStageCreate中设置
import { router } from '@kit.ArkUI';
router.addInterceptor((request: router.RouterRequest) => {
// 鉴权逻辑:检查用户登录状态
if (!isLogin && request.url.includes('profile')) {
// 重定向到登录页
return false; // 拦截跳转
}
return true; // 允许跳转
});
5. 页面跳转模式
- 标准模式:
router.RouterMode.Standard(默认),多实例跳转。 - 单实例模式:
router.RouterMode.Single,目标页若已存在则返回该实例。
router.pushUrl({
url: 'pages/Detail',
params: { id: 123 }
}, router.RouterMode.Single);
关键点:
- 页面路径需在
module.json5中配置。 - 参数传递支持基础类型和对象(需序列化)。
- 通过
router.clear()可清空历史栈。
这种设计支持灵活的页面导航与数据流管理,适用于大多数应用场景。

