HarmonyOS6 - 路由组件router和组件导航Navigation

1. 路由

官网地址:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-router

1. 概念

路由,其实可以理解为就是页面跳转,页面跳转是指从一个页面导航到另一个页面,并且可以将数据从一个页面传递到另一个页面

  • 在鸿蒙应用中,路由负责管理不同页面之间的跳转参数传递,它基于轻量级栈式管理结构,每个页面都有唯一的标识符,所有被访问过的页面都会被放置在页面栈
  • 每当页面跳转时,路由会根据标识符对页面进行入栈或出栈操作,实现页面跳转管理
  • 页面栈是一个后进先出的数据结构,用于存储鸿蒙应用中打开的页面
  • 页面栈的顶部始终是当前页,而其他页面则按照它们被打开的顺序排列在下面
  • 页面栈的最大容量32个页面,若超出此限制,可能会导致应用程序出现异常行为,例如页面无法正常压入页面栈或无法正常返回等
  • 为了避免超出页面栈的最大容量,可以在页面跳转时,选择适当的页面跳转模式

路由功能通过router对象(或称为router模块)来实现,该对象有两种导入方式

第1种导入方式如下:

js 复制代码
import router from '@ohos.router';

第2种导入方式如下:

js 复制代码
import { router } from '@kit.ArkUI';

以上两种导入方式的效果相同

2. 页面跳转

router对象提供了pushUrl()方法和replaceUrl()方法,这两个方法都可以实现页面跳转,它们的区别在于目标页是否会替换当前页,对比如下:

方法 说明
pushUrl() 目标页不会 替换当前页,而是将当前页压入页面栈以保留当前页的状态,跳转后可以通过返回操作回到当前页。这种模式适用于常规的页面导航,例如从一个列表页跳转到详情页
replaceUrl() 目标页 替换当前页,当前页会被销毁并释放资源 。跳转后无法通过返回操作回到当前页。这种模式适用于需要替换当前页的场景,例如在登录成功后直接跳转到主页

pushUrl()方法的基本语法格式如下:

js 复制代码
router.pushUrl(options, mode?, callback?);
  1. options参数是一个对象,用于设置目标页的描述信息,该对象有两个属性:
  • url属性表示目标页的路径
  • params属性表示传递的参数 (如果传递了参数,则在目标页中可以通过调用router对象getParams()方法来获取传递过来的参数。如果不需要传递参数,可以省略params属性)
  1. mode参数是可选的,用于设置跳转页面使用的模式,包括标准实例模式router.RouterMode.Standard 和单实例模式router.RouterMode.Single,它们的区别在于是否会新建目标页,默认使用标准实例模式,两种模式的说明如下表所示:
模式 说明
标准实例模式 每次跳转都会新建 一个目标页并压入栈顶。这种模式适用于需要在同一URL下展示不同内容或状态的场景,例如博客的不同文章页面
单实例模式 如果目标页已经在页面栈中,则离栈顶最近的同URL页面会被移动到栈顶并重新加载;如果目标页不存在,则按照标准实例模式跳转。这种模式适用于需要保持页面状态一致性的场景,例如购物APP类的商品详情页面

使用案例代码如下:

js 复制代码
router.pushUrl({
    url: 'pages/UserCenter',
    params: {
        nickName: '张三',
    },
}, router.RouterMode.Single)

UserCenter.ets页面这样接收参数:

js 复制代码
@State userName: string = (router.getParams() as Record<string, string>)['nickName'];
  1. callback参数是可选的,用于处理成功或失败情况的回调函数。如果省略了mode参数,callback参数可作为第2个参数

注意事项:跳转的页面必须是被@Entry装饰的组件,并且该页面必须注册到entry/src/main/resources/base/profile/main_page.json文件中

3. 页面返回

  • 当用户在一个页面完成操作后,可能需要返回到上一个页面 或者返回到指定页面,这就需要用到页面返回功能。在返回的过程中可以传递数据
  • outer对象的back()方法用于实现页面返回功能,这个方法会将用户导航到上一个页面,而且不会重新初始化上一个页面,因此上一个页面的状态和数据都会被保留

back()方法的基本语法格式如下:

js 复制代码
router.back(options?);

options是一个可选参数,该参数是一个对象,用于设置返回页的描述信息。它有url属性params属性。url属性表示返回页面的路径。params属性表示传递的参数

  • 如果省略options参数,则表示返回到上一个页面。如果传递了options参数并且传递了返回页面的路径,则表示返回到指定页面
  • 如果传递了params属性,则在返回页中可以通过调用router对象的getParams()方法来获取传递过来的参数。如果不需要传递参数,则可以省略params属性

4. Router对象提供的其他方法

除了前面讲到的pushUrl()方法、replaceUrl()方法、getParams()方法、back()方法外,router还提供了其他的方法:

方法 说明
clear() 清空页面栈中的所有历史页面,仅保留当前页面作为栈顶页面
getLength() 获取当前页面栈的数量
getState() 获取当前页面的状态信息
pushNamedRoute() 跳转到指定的命名路由页面
hideAlertBeforeBackPage() 在页面返回时禁用询问对话框
replaceNamedRoute() 用指定的命名路由页面替换当前页面,并销毁被替换的页面
showAlertBeforeBackPage() 在页面返回时弹出询问对话框

5. 页面传参

父页面传参数给子页面

父页面这样写:

js 复制代码
router.pushUrl({
    url: 'pages/PageTwo',
    params: {
        name: 'zhangsan',
    },
}, router.RouterMode.Single)

子页面这样接收参数:

js 复制代码
@State nickName: string = (router.getParams() as Record<string, string>)['nickName'];

2. 组件导航

官网地址:

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navigation

1. 概念

ArkUI中的组件导航功能包含两个重要的组件:

  • Navigation组件
  • NavDestination组件

它们分别用于实现导航页和子页

导航页用于放置导航项。子页用于显示导航项对应的内容。

2. 使用

这里我们使用如下两个页面来做测试

  1. PageOne(首页)
  2. PageTwo(详情页面)

基于上面两个页面,我们下面来演示一下,如何进行页面跳转以及页面如何进行传值

2.1. 页面跳转

首先我们需要定义系统路由表,官网地址如下:

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navigation

所以我们首先需要在工程resources/base/profile中创建route_map.json文件。添加如下配置信息:

json 复制代码
{
  "routerMap": [
    {
      "name": "PageOne",
      "pageSourceFile": "src/main/ets/pages/PageOne.ets",
      "buildFunction": "PageOneBuilder",
      "data": {
        "description": "首页"
      }
    },
    {
      "name": "PageTwo",
      "pageSourceFile": "src/main/ets/pages/PageTwo.ets",
      "buildFunction": "PageTwoBuilder",
      "data": {
        "description": "详情页"
      }
    }
  ]
}

如下:

然后在跳转目标模块的配置文件module.json5添加路由表配置,如下:

json 复制代码
"routerMap": "$profile:route_map",

如下:

最后在pages下新建下面两个页面文件:

OK,至此,我们配置信息和页面都准备好了,现在开始在PageOne页面中开始编码,代码如下:

js 复制代码
/**
 * Desc: 首页
 */
@Entry
@Component
struct PageOne {
  pathStack: NavPathStack = new NavPathStack();

  build() {
    Column() {
      Navigation(this.pathStack) {
        Text('这是首页')
          .fontSize(30)
          .fontWeight(800)

        Button('进入详情页面')
          .onClick(() => {
            //页面跳转
            this.pathStack.pushPathByName('PageTwo', '');
          })
      }
    }
    .width('100%')
    .height('100%')
  }
}

// 跳转页面入口函数
@Builder
export function PageOneBuilder() {
  PageOne();
}

PageTwo页面代码如下:

js 复制代码
/**
 * Desc: 详情页面
 */
@Component
struct PageTwo {
  @State message: string = '详情页面'

  build() {
    NavDestination() {
      Column() {
        Text('这里是详情信息!')
      }
      .height('100%')
      .width('100%')
    }
    .title(this.message)
  }
}

// 跳转页面入口函数
@Builder
export function PageTwoBuilder() {
  PageTwo();
}

启动模拟器,访问PageOne页面,如下:

点击按钮,跳转到第二个页面,如下:

OK,到目前为止,页面跳转功能就可以正常使用了

页面跳转方法官网地址如下:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#pushpath10

2.2. 传递参数

页面跳转时,如何传递参数呢?

其实非常简单,上面页面跳转时,我们传的是空,现在我们可以传递一个参数试试

PageOne改造代码后,全量如下:

js 复制代码
/**
 * Desc: 首页
 */
@Entry
@Component
struct PageOne {
  pathStack: NavPathStack = new NavPathStack();

  build() {
    Column() {
      Navigation(this.pathStack) {
        Text('这是首页')
          .fontSize(30)
          .fontWeight(800)

        Button('进入详情页面')
          .onClick(() => {
            //页面跳转
            this.pathStack.pushPathByName('PageTwo', 'PageOne Info');
          })
      }
    }
    .width('100%')
    .height('100%')
  }
}

// 跳转页面入口函数
@Builder
export function PageOneBuilder() {
  PageOne();
}

PageTwo改造代码后,全量代码如下:

js 复制代码
/**
 * Desc: 详情页面
 */
@Component
struct PageTwo {
  @State message: string = '详情页面';
  @State param: string = ''; //保存从首页传来的参数数据

  build() {
    NavDestination() {
      Column() {
        Text('这里是详情信息!')
        Text('首页传过来数据:' + this.param)
      }
      .height('100%')
      .width('100%')
    }
    .title(this.message)
    .onReady((context: NavDestinationContext) => {
      //将首页传过来的数据赋值给变量param
      this.param = context.pathInfo.param as string;
    })
  }
}

// 跳转页面入口函数
@Builder
export function PageTwoBuilder() {
  PageTwo();
}

测试如下:

那现在从PageTwo页面翻译PageOne时,如何给PageOne传参数呢?

此时需要在PageOne页面中修改pushPathByName方法了,加上第三个参数,如下:

PageOne页面修改后,全量代码如下:

js 复制代码
/**
 * Desc: 首页
 */
@Entry
@Component
struct PageOne {
  pathStack: NavPathStack = new NavPathStack();
  @State param: string = ''; //保存从相亲页面传来的参数数据

  build() {
    Column() {
      Navigation(this.pathStack) {
        Text('这是首页')
          .fontSize(30)
          .fontWeight(800)

        Text('详情页传过来数据:' + this.param)

        Button('进入详情页面')
          .onClick(() => {
            //页面跳转
            this.pathStack.pushPathByName('PageTwo', 'PageOne Info', (popInfo) => {
              //popInfo对象保存着详情页传过来的数据
              console.log('popInfo====' + JSON.stringify(popInfo))
              this.param = popInfo.result['info'];
            });
          })
      }
    }
    .width('100%')
    .height('100%')
  }
}

// 跳转页面入口函数
@Builder
export function PageOneBuilder() {
  PageOne();
}

PageTwo页面修改后,全量代码如下:

js 复制代码
/**
 * Desc: 详情页面
 */
@Component
struct PageTwo {
  @State message: string = '详情页面';
  @State param: string = ''; //保存从首页传来的参数数据
  pathStack: NavPathStack | undefined = undefined;
  popInfo: PopInfo = {
    info: 'data from PageTwo'
  }

  build() {
    NavDestination() {
      Column() {
        Text('这里是详情信息!')
        Text('首页传过来数据:' + this.param)
      }
      .height('100%')
      .width('100%')
    }
    .title(this.message)
    .onReady((context: NavDestinationContext) => {
      //将首页传过来的数据赋值给变量param
      this.param = context.pathInfo.param as string;
      //为pathStack变量赋值
      this.pathStack = context.pathStack;
    })
    .onBackPressed(() => {
      //将 popInfo 对象数据传回到上一页
      this.pathStack?.pop(this.popInfo);
      return true;
    })
  }
}

// 跳转页面入口函数
@Builder
export function PageTwoBuilder() {
  PageTwo();
}

interface PopInfo {
  info: string
}

点击按钮跳转到PageTwo如下:

然后再点击左上角的返回按钮,返回到首页,如下:

可以看到,确实可以在首页获取到详情页传递过来的数据,测试成功

3. 总结

本文主要介绍了路由组件和组件导航的使用方式,大家在实际开发过程中,可以根据情况选用合适的方式进行页面跳转

相关推荐
坚果派·白晓明2 小时前
在鸿蒙设备上快速验证由lycium工具快速交叉编译的C/C++三方库
c语言·c++·harmonyos·鸿蒙·编程语言·openharmony·三方库
熊猫钓鱼>_>4 小时前
移动端开发技术选型报告:三足鼎立时代的开发者指南(2026年2月)
android·人工智能·ios·app·鸿蒙·cpu·移动端
ITUnicorn4 小时前
【HarmonyOS6】ArkTS 自定义组件封装实战:动画水杯组件
华为·harmonyos·arkts·鸿蒙·harmonyos6
晚霞的不甘4 小时前
Flutter for OpenHarmony 构建简洁高效的待办事项应用 实战解析
flutter·ui·前端框架·交互·鸿蒙
廖松洋(Alina)5 小时前
【收尾以及复盘】flutter开发鸿蒙APP之成就徽章页面
flutter·华为·开源·harmonyos·鸿蒙
廖松洋(Alina)5 小时前
【收尾以及复盘】flutter开发鸿蒙APP之打卡日历页面
flutter·华为·开源·harmonyos·鸿蒙
廖松洋(Alina)5 小时前
【收尾以及复盘】flutter开发鸿蒙APP之本月数据统计页面
flutter·华为·开源·harmonyos·鸿蒙
星空下的月光影子20 小时前
鸿蒙应用开发中的性能优化与资源管理
鸿蒙系统
我讲个笑话你可别哭啊1 天前
鸿蒙ArkTS快速入门
前端·ts·arkts·鸿蒙·方舟开发框架
mocoding1 天前
使用已经完成鸿蒙化适配的Flutter本地持久化存储三方库shared_preferences让你的应用能够保存用户偏好设置、缓存数据等
flutter·华为·harmonyos·鸿蒙