鸿蒙极速入门(五)-路由管理(Router)

页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOS提供了Router模块,通过不同的url地址,可以方便地进行页面路由,轻松地访问不同的页面。

一、基础使用

Router模块提供了两种跳转模式,分别是router.pushUrl()和router.replaceUrl()。这两种模式决定了目标页面是否会替换当前页。

  • router.pushUrl():目标页面不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用router.back()方法返回到当前页。
  • router.replaceUrl():目标页面会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。

注意:页面栈的最大容量为32个页面。如果超过这个限制,可以调用router.clear()方法清空历史页面栈,释放内存空间。

Router模块提供了两种实例模式,分别是Standard和Single。这两种模式决定了目标url是否会对应多个实例。

  • Standard:多实例模式,也是默认情况下的跳转模式。目标页面会被添加到页面栈顶,无论栈中是否存在相同url的页面。
  • Single:单实例模式。如果目标页面的url已经存在于页面栈中,则会将离栈顶最近的同url页面移动到栈顶,该页面成为新建页。如果目标页面的url在页面栈中不存在同url页面,则按照默认的多实例模式进行跳转。

在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。

import router from '@ohos.router';

跳转示例

1.普通跳转

function onJumpClick(): void {
  router.pushUrl({
    url: 'pages/Detail' // 目标url
  });
}

2.带跳转模式和跳转结果

比如从其他页面,跳转到登录页面(全局唯一)

function onJumpClick(): void {
  router.pushUrl({
    url: 'pages/Detail' // 目标url
  }, router.RouterMode.Single, (err) => {
    if (err) {
      console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
      return;
    }
    console.info('Invoke pushUrl succeeded.');
  });
}

3.替换原页面

比如从启动页面跳转到首页,同时需要销毁启动页

function onJumpClick(): void {
  router.replaceUrl({
    url: 'pages/Profile' // 目标url
  });
}

4.带参数

在调用Router模块的方法时,添加一个params属性,并指定一个对象作为参数:

class DataModelInfo {
  age: number;
}

class DataModel {
  id: number;
  info: DataModelInfo;
}

function onJumpClick(): void {
  // 在Home页面中
  let paramsInfo: DataModel = {
    id: 123,
    info: {
      age: 20
    }
  };

  router.pushUrl({
    url: 'pages/Detail', // 目标url
    params: paramsInfo // 添加params属性,传递自定义参数
  }, (err) => {
    if (err) {
      console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
      return;
    }
    console.info('Invoke pushUrl succeeded.');
  })
}

在目标页面中,可以通过调用Router模块的getParams()方法来获取传递过来的参数。

const params = router.getParams(); // 获取传递过来的参数对象
const id = params['id']; // 获取id属性的值
const age = params['info'].age; // 获取age属性的值

页面返回

1.返回上一页

router.back();

2.返回到指定页面

router.back({
  url: 'pages/Home' // 指定url
});

3.返回到指定页面,并传递自定义参数信息。

router.back({
  url: 'pages/Home',
  params: {
    info: '来自Home页'
  }
});

4.目标页面中,在需要获取参数的位置调用router.getParams()方法即可,例如在onPageShow()生命周期回调中:

onPageShow() {
  const params = router.getParams(); // 获取传递过来的参数对象
  const info = params['info']; // 获取info属性的值
}

页面返回的特别说明

当使用router.back()方法返回到指定页面时,该页面会被重新压入栈顶,而原栈顶页面(包括)到指定页面(不包括)之间的所有页面栈都将被销毁。

如果使用router.back()方法返回到原来的页面,原页面不会被重复创建,因此使用@State声明的变量不会重复声明,也不会触发页面的aboutToAppear()生命周期回调。如果需要在原页面中使用返回页面传递的自定义参数,可以在需要的位置进行参数解析。例如,在onPageShow()生命周期回调中进行参数解析。

二、命名路由

为了支持组件化,HarmonyOS支持多HAP机制共享包机制

在开发中为了跳转到共享包中的页面,可以使用router.pushNamedRoute()来实现,也就是命名路由的方式。

示例

在想要跳转到的共享包页面里,给@Entry修饰的自定义组件命名:

// library/src/main/ets/pages/Index.ets
// library为新建共享包自定义的名字
@Entry({ routeName : 'myPage' })
@Component
struct MyComponent {
}

配置成功后需要在需要跳转的页面中引入命名路由的页面:

// entry/src/main/ets/pages/Index.ets
import router from '@ohos.router';
import 'library/src/main/ets/pages/Index' // 引入共享包library中的命名路由页面

@Entry
@Component
struct Index {
  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Text('Hello World')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20 })
        .backgroundColor('#ccc')
        .onClick(() => { // 点击跳转到其他共享包中的页面
          try {
            router.pushNamedRoute({
              name: 'myPage',
              params: {
                data1: 'message',
                data2: {
                  data3: [123, 456, 789]
                }
              }
            })
          } catch (err) {
            console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
          }
        })
    }
    .width('100%')
    .height('100%')
  }
}

其他

基于命名路由技术方案时,建议将路由URL统一放在一个文件中做管理。