# 7.4:页面跳转(Router、Ability)

页面跳转可以分为页面内跳转和页面间跳转,页面内跳转是指所跳转的页面在同一个 Ability 内部,它们之间的跳转可以使用 Router 或者 Navigator 的方式;页面间跳转是指所跳转的页面属与不同的 Ability ,这种跳转需要借助 featureAbility 实现,跳转示意图如下所示:

7_4

本节将简单介绍这两种方式的页面跳转。

# 7.4.1:页面内跳转

页面内跳转的实现比较简单,直接使用ArkUI开发框架提供的 Router 或者 Navigator 就可以了, Navigator 本质上是对 Router 的封装,这里就简单介绍一下 Router 的使用,想了解 Navigator 的小伙伴请参考官网文档。

# 7.4.1.1:router定义介绍

declare namespace router {
  function push(options: RouterOptions):void;
  function replace(options: RouterOptions):void;
  function back(options?: RouterOptions ):void;
  function clear():void;
  function getLength():string;
  function getState():RouterState;
  function enableAlertBeforeBackPage(options: EnableAlertOptions):void;
  function disableAlertBeforeBackPage():void;
  function getParams(): Object;
}
1
2
3
4
5
6
7
8
9
10
11
  • push:打开新的页面,新页面在栈顶位置, RouterOptions 定义了以下参数:
    • url:目标页面的路径,该路径必须在 config.jsonpages 下配置,否则不起作用。
    • params:可选参数,向目标页面传递参数。
  • replace:新页面替换当前页面并把当前页面销毁。
  • back:返回上一页。
  • clear:清空路由栈里的其它页面。
  • getLength:获取当前路由栈里的页面数量。
  • getState:获取当前页面的状态, RouterState参数说明如下:
    • index:当前页面是第几个打开的。
    • path:当前页面的路径。
    • name:当前页面的名称。
  • enableAlertBeforeBackPage
  • disableAlertBeforeBackPage
  • getParams:获取通过路由传递过来的参数。

# 7.4.1.2:router使用介绍

  • 引入router

    使用 router 之前,先要引入 router ,引入方式如下:

    import router from '@ohos.router';
    
    1
  • 页面跳转

    页面跳转使用 router.push 方法,简单样例如下所示:

    // 第一个页面
    @Entry @Component struct ComponentTest {
      build() {
        Column({space: 10}) {
          Text('第一个页面')
            .fontSize(30)
            .width('100%')
            .textAlign(TextAlign.Center)
    
          Button('打开下一页')
            .onClick(() => {
              router.push({          // 使用push入栈一个新页面
                url: "pages/second"  // 通过url指定新打开的页面
              })
            })
        }
        .size({width: '100%', height: '100%'})
      }
    }
    
    // 第二个页面
    @Entry @Component struct Second {
    
      build() {
        Column({space: 10}) {
          Text('第二个页面')
            .fontSize(30)
            .width('100%')
            .textAlign(TextAlign.Center)
    
          Button('返回上一页')
            .onClick(() => {
              router.back(); // 返回上一页,当前页面会销毁
            })
        }
        .size({width: '100%', height: '100%'})
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38

    样例运行结果如下所示:

    7_4_1_2_1
  • 参数传递

    当通过 router 打开新页面需要传递参数时,可以使用 RouterOptionsparams 参数传递一个对象,然后在接收方以 router.getParams() 的方式拿到传递过来的对象,取值的话以 .key 的形式取值(注意:从 3.1.6.5 版本起,取值方式变更为 ['key'] 的形式),样例如下:

    // 第一个页面
    @Entry @Component struct ComponentTest {
    
      build() {
        Column({space: 10}) {
          Text('第一个页面')
            .fontSize(30)
            .width('100%')
            .textAlign(TextAlign.Center)
    
          Button('打开下一页')
            .onClick(() => {
              router.push({
                url: "pages/second",  // 打开新页面
                params: {value: 'Hi'} // 给新页面传递一个对象,key为value,取值以.value的形式
              })
            })
        }
        .size({width: '100%', height: '100%'})
      }
    }
    
    
    // 第二个页面
    @Entry @Component struct Second {
    
      // 3.1.5.5版本之前,取值方式为:router.getParams().key
      private value: string = router.getParams().value;
    
      // 从3.1.6.5版本起,取值方式为:router.getParams()['key']
      private value: string = router.getParams()['value'];
    
    
    
      build() {
        Column({space: 10}) {
          Text('第二个页面:' + this.value) // 使用获取过来的参数
            .fontSize(30)
            .width('100%')
            .textAlign(TextAlign.Center)
    
          Button('返回上一页')
            .onClick(() => {
              router.back();              // 返回上一页
            })
        }
        .size({width: '100%', height: '100%'})
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49

    样例运行结果如下图所示:

    7_4_1_2_2

    📢:感谢 lx2323658175 (opens new window) 指出 3.1.6.5 版本 router 的取值方式做了变更,笔者写该电子书时使用的 SDK 版本为 3.1.5.5,该版本的取值方式为 router.getParams().key 的形式,从 3.1.6.5 版本起,取值方式变更为:router.getParams()['key'] 的形式,特此说明。

# 7.4.2:页面间跳转

页面间跳转需要借助 featureAbility 模块的 startAbility() 方法,该方法和 router 的功能类似,可以支持参数传递以及打开指定页面等。

# 7.4.2.1:featureAbility定义介绍

declare namespace featureAbility {
  /**省略部分方法*/
  function startAbility(parameter: StartAbilityParameter, callback: AsyncCallback<number>): void;
  function startAbility(parameter: StartAbilityParameter): Promise<number>;
  function startAbilityForResult(parameter: StartAbilityParameter, callback: AsyncCallback<AbilityResult>): void;
  function startAbilityForResult(parameter: StartAbilityParameter): Promise<AbilityResult>;
}
1
2
3
4
5
6
7
  • startAbility:打开指定 Ability ,在不指定开目标 Ability 里的页面时,则默认打开 Ability 的第一个页面。
    • parameter:设置打开 Ability 的参数,说明如下:
      • want:打开目标 Ability 的配置项。
        • bundleName:目标 Ability 的包名称。
        • abilityName:目标 Ability 的全路径。
        • params:传递给目标 Ability 的参数。可以在该参数里指定需要打开的页面。

# 7.4.2.2:打开Ability的默认首页面

  1. 创建第二个 Ability ,依次点击 File -> new -> Ablity -> Empty Page Ability(eTS) ,添加 SettingAbility ,如下图所示:

    7_4_2_2_1

    点击 Finish 后, OpenHarmony 代码结构如下图所示:

    7_4_2_2_2
  2. 在 default 的 pages 下的 index.ets 添加跳转功能:引入 featureAbility 模块,然后通过 featureAbility 的 startAbility() 方法打开目标 Ability。

    // 引入featureAbility
    import featureAbility from '@ohos.ability.featureAbility';
    
    @Entry @Component struct Index {
    
      build() {
        Column() {
          Button('open about ability')
            .onClick(() => {
            	// 打开目标Ability
              featureAbility.startAbility({
                want: {
                  // 目标Ability所在的bundleName,也就是config.json里配置的bundleName
                  bundleName: "com.example.myapplication",
                  // 目标Ability的全路径
                  abilityName: "com.example.myapplication.SettingAbility"
                }
              })
              .then((data) => {
                console.info('Operation successful. Data: ' + JSON.stringify(data))
              })
              .catch((error) => {
                console.error('Operation failed. Cause: ' + JSON.stringify(error));
              })
            })
        }
        .padding(10)
        .width('100%')
        .height('100%')
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
  3. 修改SettingAbility的默认首页面,添加如下文案:

    @Entry @Component struct Index {
      build() {
        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
          Text('我是SettingAbility的默认首页面')
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
        }
        .width('100%')
        .height('100%')
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    运行结果如下图所示:

    7_4_2_2_3

# 7.4.2.3:打开Ability的指定页面

  1. 在 SettingAbility 的 pages 下添加第二个页面:second.ets,代码如下所示:

    @Entry @Component struct Second {
      build() {
        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
          Text('你好,我是SettingAbility的第二个页面')
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
        }
        .width('100%')
        .height('100%')
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  2. 修改打开 Ability 的代码,添加 url 参数,代码如下:

    featureAbility.startAbility({
      want: {
        bundleName: "com.example.myapplication",
        abilityName: "com.example.myapplication.SettingAbility",
        // 添加uri参数,指定打开SettingAbility下的second页面。
        uri: "pages/second"
      }
    })
    .then((data) => {
      console.info('Operation successful. Data: ' + JSON.stringify(data))
    })
    .catch((error) => {
      console.error('Operation failed. Cause: ' + JSON.stringify(error));
    })
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    运行结果如下所示:

    7_4_2_2_4

# 7.4.3:小结

本节简单介绍了页面内和页面间的跳转方法以及在跳转过程中的参数传递和取值,另外请读者看一个场景:从不同的页面跳转到B页面,但是B页面需要登录才可以跳转,一般做法是在打开B页面时判断是否登录,如果登录了直接跳转B页面否则跳转登录页面去登录,登录成功后再跳转B页面。以上场景请读者思考一下,能否把类似校验逻辑基于 Router 封装一个更强大的 SuperRouter 出来?笔者也写了一版具有类似功能的 Router ,后续会开源出来,也期待读者能自己动手写一下开源出来,大家一起学习,一起为 OpenHarmony 生态发展贡献力量。

(adsbygoogle = window.adsbygoogle || []).push({});
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2