页面路由(@ohos.router)

页面路由指在应用程序中实现不同页面之间的跳转和数据传递。Router模块通过不同的url地址,可以方便地进行页面路由,轻松地访问不同的页面。本文将从页面跳转页面返回页面返回前增加一个询问框命名路由几个方面介绍Router模块提供的功能。

页面跳转与参数接收

页面跳转

页面跳转是开发过程中的一个重要组成部分。在使用应用程序时,通常需要在不同的页面之间跳转,有时还需要将数据从一个页面传递到另一个页面。

router.pushUrl({
  url: 'pages/Second',
  params: {
    src: 'Index页面传来的数据',
  }
}, router.RouterMode.Single)

router.replaceUrl({
  url: 'pages/Second',
  params: {
    src: 'Index页面传来的数据',
  }
}, router.RouterMode.Single)

参数接收

通过调用router.getParams()方法获取Index页面传递过来的自定义参数

import router from '@ohos.router';

@Entry
@Component
struct Second {
  @State src: string = router.getParams()?.['src'];
  // 页面刷新展示
  ...
}

页面返回

页面返回

当用户在一个页面完成操作后,通常需要返回到上一个页面或者指定页面,这就需要用到页面返回功能。在返回的过程中,可能需要将数据传递给目标页面,这就需要用到数据传递功能。

Second页面中,可以通过调用router.back()方法实现返回到上一个页面,或者在调用router.back()方法时增加可选的options参数(增加url参数)返回到指定页面,也可以返回命名路由页面。

import router from '@ohos.router';
// 返回上级
router.back();
// 返回制定页面
router.back({ url: 'pages/Index' });
// myPage为返回的命名路由页面别名
router.back({
  url: 'myPage' 
});

页面返回询问对话框

在开发应用时,为了避免用户误操作或者丢失数据,有时候需要在用户从一个页面返回到另一个页面之前,弹出一个询问框,让用户确认是否要执行这个操作。

  • 启用页面返回询问对话框功能:

    使用 router.enableBackPageAlert() 方法开启页面返回询问对话框功能。这个功能只针对当前页面生效。在调用 router.pushUrl() 或 router.replaceUrl() 方法后,跳转到的新页面被视为新建页面,因此在页面返回之前需要先调用 router.enableBackPageAlert() 方法,以启用页面返回询问对话框功能。

    router.enableBackPageAlert({
      message: 'Message Info'
    });
    
    router.back();
    
  • 关闭页面返回询问对话框功能:

    如果需要关闭页面返回询问对话框功能,可以使用 router.disableAlertBeforeBackPage() 方法。这个方法用于在特定情况下禁用询问对话框,以确保在页面返回时不会出现确认提示。

  • 自定义询问框

    自定义询问框的方式,可以使用弹窗或者自定义弹窗实现。这样可以让应用界面与系统默认询问框有所区别,提高应用的用户体验度。

    import router from '@ohos.router';
    import promptAction from '@ohos.promptAction';
    import { BusinessError } from '@ohos.base';
    
    function onBackClick() {
      // 弹出自定义的询问框
      promptAction.showDialog({
        message: '您还没有完成支付,确定要返回吗?',
        buttons: [
          {
            text: '取消',
            color: '#FF0000'
          },
          {
            text: '确认',
            color: '#0099FF'
          }
        ]
      }).then((result:promptAction.ShowDialogSuccessResponse) => {
        if (result.index === 0) {
          // 用户点击了“取消”按钮
          console.info('User canceled the operation.');
        } else if (result.index === 1) {
          // 用户点击了“确认”按钮
          console.info('User confirmed the operation.');
          // 调用router.back()方法,返回上一个页面
          router.back();
        }
      }).catch((err:Error) => {
        let message = (err as BusinessError).message
        let code = (err as BusinessError).code
        console.error(`Invoke showDialog failed, code is ${code}, message is ${message}`);
      })
    }
    

参数接收

在Second页面中,调用router.back()方法返回上一个页面或者返回指定页面时,根据需要继续增加自定义参数,例如在返回时增加一个自定义参数src。

router.back({
  url: 'pages/Index',
  params: {
    src: 'Second页面传来的数据',
  }
})

从Second页面返回到Index页面。在Index页面通过调用router.getParams()方法,获取Second页面传递过来的自定义参数。

在调用 router.back() 方法时,不会新建页面,而是返回到原来的页面。在原来页面中使用 @State 声明的变量不会重复声明,也不会触发页面的 aboutToAppear() 生命周期回调。因此,不能直接在变量声明以及页面的 aboutToAppear() 生命周期回调中接收和解析 router.back() 传递过来的自定义参数。

这意味着当使用 router.back() 返回到前一个页面时,需要采取其他方式来传递和处理自定义参数,因为原页面的状态和生命周期不会重新初始化。

可以放在业务需要的位置进行参数解析。示例代码在Index页面中的onPageShow()生命周期回调中进行参数的解析。

import router from '@ohos.router';

@Entry
@Component
struct Index {
  @State src: string = '';

  onPageShow() {
    this.src = router.getParams()?.['src'];
  }

  // 页面刷新展示
  ...
}

命名路由

在开发中为了跳转到共享包Har或者Hsp中的页面(即共享包中路由跳转),可以使用router.pushNamedRoute()来实现。

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

    // library/src/main/ets/pages/Index.ets
    // library为新建共享包自定义的名字
    @Entry({ routeName: 'myPage' })
    @Component
    export struct MyComponent {
      build() {
        Row() {
          Column() {
            Text('Library Page')
              .fontSize(50)
              .fontWeight(FontWeight.Bold)
          }
          .width('100%')
        }
        .height('100%')
      }
    }
    
  • 配置成功后需要在跳转的页面中引入命名路由的页面:

    import router from '@ohos.router';
    import { BusinessError } from '@ohos.base';
    import('@ohos/library/src/main/ets/pages/Index');  // 引入共享包中的命名路由页面
    @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) {
                let message = (err as BusinessError).message
                let code = (err as BusinessError).code
                console.error(`pushNamedRoute failed, code is ${code}, message is ${message}`);
              }
            })
        }
        .width('100%')
        .height('100%')
      }
    }
    
  • 在当前应用包的oh-package.json5文件中配置依赖。

"dependencies": {
   "@ohos/library": "file:../library",
   ...
}
07-17 10:07