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. 总结

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

相关推荐
小雨下雨的雨6 小时前
Flutter鸿蒙共赢——墨染算法:柏林噪声与鸿蒙生态中的数字水墨意境
算法·flutter·华为·交互·harmonyos·鸿蒙
奋斗的小青年!!8 小时前
鸿蒙使用Flutter粒子效果实战
flutter·harmonyos·鸿蒙
行者9613 小时前
Flutter与OpenHarmony跨平台分享组件深度实践
flutter·harmonyos·鸿蒙
行者9613 小时前
Flutter跨平台开发在OpenHarmony上的评分组件实现与优化
开发语言·flutter·harmonyos·鸿蒙
码界奇点14 小时前
基于Spring Cloud微服务架构的电商系统设计与实现
spring cloud·微服务·架构·毕业设计·鸿蒙系统·源代码管理
kirk_wang17 小时前
Flutter 三方库在 OpenHarmony 上的适配之路:以 geolocator 为例
flutter·移动开发·跨平台·arkts·鸿蒙
奋斗的小青年!!21 小时前
Flutter跨平台开发适配OpenHarmony:手势识别实战应用
flutter·harmonyos·鸿蒙
行者961 天前
Flutter跨平台开发:安全检测组件适配OpenHarmony
flutter·harmonyos·鸿蒙
小雨下雨的雨1 天前
Flutter 框架跨平台鸿蒙开发 —— GridView 控件之多维网格美学
flutter·华为·交互·harmonyos·鸿蒙系统