HarmonyOS 路由跳转示例

76 阅读3分钟

HarmonyOS 路由跳转指南

1. 基础路由跳转(Router)

1.1 使用 router.pushUrl 进行跳转

最基本的页面跳转方式,支持传递参数:

router.pushUrl({
  url: 'pages/router/RouterOnePage',
  params: { message: '普通跳转' }
})

1.2 跨包跳转,使用命名路由跳转

通过路由名称进行跳转:支持跳转到其他模块的页面:

router.pushNamedRoute({
  name: 'TestRouterPage',
  params: {
    data1: 'message',
    data2: {
      data3: [123, 456, 789]
    }
  }
})

1.3 返回上一页

Button('回到上一页')
  .onClick(() => {
    router.back()
  })

1.4 完整代码

1.4.1 主页面(RouterJumpPage)
@Entry
@Component
struct RouterJumpPage {
  @State message: string = 'Router跳转示例';

  build() {

    Column() {
      Text(this.message)
        .fontSize(36)
        .margin({ top: 20, left: 20 })
        .fontWeight(FontWeight.Bold)

      Button('跳转同模块页面RouterOnePage')
        .height(50)
        .margin({ top: 20, left: 20 })
        .onClick(() => {
          router.pushUrl({ url: 'pages/router/RouterOnePage' })
        })
      Button('跨包跳转到子模块页面')
        .height(50)
        .margin({ top: 20, left: 20 })
        .onClick(() => {
          try {
            router.pushNamedRoute({
              name: 'TestRouterPage',
              params: {
                data1: 'message',
                data2: {}
              }
            })
          } 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%')
    .alignItems(HorizontalAlign.Start)
    .justifyContent(FlexAlign.Start)
  }
}
1.4.2 同模块子页面(RouterOnePage)
@Entry
@Component
export struct NavigationOnePage {
  @State message: string = 'Navigation 普通跳转的二级界面';
  derivedStack: NavPathStack = new NavPathStack();
  curStringifyParam: string = "NA";

  build() {
    NavDestination() {
      Column() {
        Column() {
          Text('current page param info:')
            .margin(10)
            .fontSize(25)
            .fontWeight(FontWeight.Bold)
            .textAlign(TextAlign.Start)
          Text(this.curStringifyParam)
            .margin(20)
            .fontSize(20)
            .textAlign(TextAlign.Start)
        }.backgroundColor(Color.Pink)

        Button('回到上一页', { stateEffect: true, type: ButtonType.Capsule })
          .width('40%')
          .height(50)
          .margin(20)
          .onClick(() => {
            // 返回到上一页
            this.derivedStack.pop();
          })
      }
      .height('100%')
      .width('100%')
      .alignItems(HorizontalAlign.Start)
      .justifyContent(FlexAlign.Start)
    }
    .title(this.message)
    .onReady((context: NavDestinationContext) => {
      console.log('[derive-test] reached PageOne's onReady');
      // get derived stack from navdestinationContext
      this.derivedStack = context.pathStack as NavPathStack;
      // console.log('[derive-test] -- got derivedStack: ' + this.derivedStack.id);
      this.curStringifyParam = JSON.stringify(context.pathInfo.param);
      console.log('[derive-test] -- got param: ' + this.curStringifyParam);
    })
  }
}
1.4.3 跨包子页面(TestRouterPage)
import { router } from "@kit.ArkUI";

@Entry({ routeName: 'TestRouterPage' })
@Component
export struct TestRouterPage {
  @State message: string = '子模块的界面';

  build() {
    Column() {
      Text(this.message)
        .fontSize(36)
        .margin({ top: 20, left: 20 })
        .fontWeight(FontWeight.Bold)

      Button('回到首页', { stateEffect: true, type: ButtonType.Capsule })
        .width('40%')
        .height(50)
        .margin(20)
        .onClick(() => {
          router.back()
        })
    }.width('100%').height('100%')
    .alignItems(HorizontalAlign.Start)
    .justifyContent(FlexAlign.Start)
  }
}

2. Navigation 导航跳转

2.1 基础 Navigation 跳转

使用 Navigation 组件进行页面导航:

Navigation(this.derivedStack)
{
  Button('Navigation 普通跳转')
    .onClick(() => {
      this.derivedStack.pushPath({
        name: 'NavigationOnePage',
        param: new param('push NavigationOnePage when stack size: ' + this.derivedStack.size())
      });
    })
}

2.2 跨包 Navigation 跳转

支持跨包使用 Navigation 进行跳转:

this.derivedStack.pushPath({
  name: 'LoginPage',
  param: new param('push LoginPage when stack size: ' + this.derivedStack.size())
});

2.3 使用 Navigation 返回

Button('回到上一页')
  .onClick(() => {
    this.derivedStack.pop();
  })

2.4 完整示例

2.4.1 主页面(NavigationJumpPage)
@Entry
@Component
struct NavigationJumpPage{
  @State message: string = '使用NavDestination跳转';
  // 创建一个页面栈对象并传入Navigation
  derivedStack: NavPathStack = new NavPathStack();

  aboutToAppear():void {
    // this.derivedStack.setId('origin stack');
  }

  @Builder
  pageMap(name:string){
    if (name === 'NavigationOnePage') {
      NavigationOnePage();
    } else if (name === 'LoginPage') {
      TestNavigationPage();
    }
  }

  build(){
    Navigation(this.derivedStack){
      Column(){
        Button('Navigation 普通跳转')
          .height(50)
          .margin({ top: 20, left: 20 })
          .onClick(() => {
            this.derivedStack.pushPath({
              name: 'NavigationOnePage',
              param: new param('push NavigationOnePage when stack size: ' + this.derivedStack.size())
            });
          })
        Button('TestNavigationPage 跨包跳转')
          .height(50)
          .margin({ top: 20, left: 20 })
          .onClick(() => {
            this.derivedStack.pushPath({
              name: 'LoginPage',
              param: new param('push TestNavigationPage when stack size: ' + this.derivedStack.size())
            });
          })
      }
      .
      width('100%')
        .height('100%')
        .alignItems(HorizontalAlign.Start)
        .justifyContent(FlexAlign.Start)
    }
    .
    title(this.message)
      .navDestination(this.pageMap)
  }
}
2.4.2 同模块的子页面(NavigationOnePage)
@Entry
@Component
export struct NavigationOnePage{
  @State message: string = 'Navigation 普通跳转的二级界面';
  derivedStack: NavPathStack = new NavPathStack();
  curStringifyParam: string = "NA";

  build(){
    NavDestination(){
      Column(){
        Column(){
          Text('current page param info:')
            .margin(10)
            .fontSize(25)
            .fontWeight(FontWeight.Bold)
            .textAlign(TextAlign.Start)
          Text(this.curStringifyParam)
            .margin(20)
            .fontSize(20)
            .textAlign(TextAlign.Start)
        }
        .
        backgroundColor(Color.Pink)

        Button('回到上一页', { stateEffect: true, type: ButtonType.Capsule })
          .width('40%')
          .height(50)
          .margin(20)
          .onClick(() => {
            // 返回到上一页
            this.derivedStack.pop();
          })
      }
      .
      height('100%')
        .width('100%')
        .alignItems(HorizontalAlign.Start)
        .justifyContent(FlexAlign.Start)
    }
    .
    title(this.message)
      .onReady((context: NavDestinationContext) => {
        console.log('[derive-test] reached PageOne\'s onReady');
        // get derived stack from navdestinationContext
        this.derivedStack = context.pathStack as NavPathStack;
        // console.log('[derive-test] -- got derivedStack: ' + this.derivedStack.id);
        this.curStringifyParam = JSON.stringify(context.pathInfo.param);
        console.log('[derive-test] -- got param: ' + this.curStringifyParam);
      })
  }
}

2.4.3 跨包的子页面(TestNavigationPage)
@Entry
@Component
export struct TestNavigationPage{
  @State message: string = 'NavigationPage跨包跳转的二级界面';
  derivedStack: NavPathStack = new NavPathStack();
  curStringifyParam: string = "NA";
  build(){
    NavDestination(){
      Column(){
        Text('current page param info:')
          .margin(10)
          .fontSize(25)
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Start)
        Text(this.curStringifyParam)
          .margin(20)
          .fontSize(20)
          .textAlign(TextAlign.Start)

        Button('回到上一页', { stateEffect: true, type: ButtonType.Capsule })
          .width('40%')
          .height(50)
          .margin(20)
          .onClick(() => {
            this.derivedStack.pop();
          })
      }
      .
      width('100%')
        .height('100%')
        .alignItems(HorizontalAlign.Start)
        .justifyContent(FlexAlign.Start)
    }.title(this.message)
     .onReady((context: NavDestinationContext) => {
        console.log('[derive-test] reached PageOne\'s onReady');
        // get derived stack from navdestinationContext
        this.derivedStack = context.pathStack as NavPathStack;
        // console.log('[derive-test] -- got derivedStack: ' + this.derivedStack.id);
        this.curStringifyParam = JSON.stringify(context.pathInfo.param);
        console.log('[derive-test] -- got param: ' + this.curStringifyParam);
      })
  }
}

3. 注意事项

  1. 路由跳转时需要注意处理异常情况
  2. 跨包跳转时需要确保目标页面已经注册
  3. Navigation 跳转需要正确配置 NavDestination
  4. 参数传递时注意类型安全
  5. 返回操作时注意页面栈的状态