• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Router切换Navigation
2
3## 架构差异
4从ArkUI组件树层级上来看,原先由Router管理的page在页面栈管理节点stage的下面。Navigation作为导航容器组件,可以挂载在单个page节点下,也可以叠加、嵌套。Navigation管理了标题栏、内容区和工具栏,内容区用于显示用户自定义页面的内容,并支持页面的路由能力。Navigation的这种设计上有如下优势:
5
6![image](figures/Navigation和Router架构图.png)
7
81. 接口上显式区分标题栏、内容区和工具栏,实现更加灵活的管理和UX动效能力;
9
102. 显式提供路由容器概念,由开发者决定路由容器的位置,支持在全模态、半模态、弹窗中显示;
11
123. 整合UX设计和一多能力,默认提供统一的标题显示、页面切换和单双栏适配能力;
13
144. 基于通用[UIBuilder](../quick-start/arkts-builder.md)能力,由开发者决定页面别名和页面UI对应关系,提供更加灵活的页面配置能力;
15
165. 基于组件属性动效和共享元素动效能力,将页面切换动效转换为组件属性动效实现,提供更加丰富和灵活的切换动效;
17
186. 开放了页面栈对象,开发者可以继承,能更好的管理页面显示。
19
20## 能力对比
21
22| 业务场景                                      | Navigation                            | Router                                 |
23| --------------------------------------------- | ------------------------------------- | -------------------------------------- |
24| 一多能力                                      | 支持,Auto模式自适应单栏跟双栏显示    | 不支持                                 |
25| 跳转指定页面                                  | pushPath & pushDestination            | pushUrl & pushNameRoute                |
26| 跳转HSP中页面                                 | 支持                                  | 支持                                   |
27| 跳转HAR中页面                                 | 支持                                  | 支持                                   |
28| 跳转传参                                      | 支持                                  | 支持                                   |
29| 获取指定页面参数                              | 支持                                  | 不支持                                 |
30| 传参类型                                      | 传参为对象形式                        | 传参为对象形式,对象中暂不支持方法变量 |
31| 跳转结果回调                                  | 支持                                  | 支持                                   |
32| 跳转单例页面                                  | 支持                                  | 支持                                   |
33| 页面返回                                      | 支持                                  | 支持                                   |
34| 页面返回传参                                  | 支持                                  | 支持                                   |
35| 返回指定路由                                  | 支持                                  | 支持                                   |
36| 页面返回弹窗                                  | 支持,通过路由拦截实现                | showAlertBeforeBackPage                |
37| 路由替换                                      | replacePath & replacePathByName       | replaceUrl & replaceNameRoute          |
38| 路由栈清理                                    | clear                                 | clear                                  |
39| 清理指定路由                                  | removeByIndexes & removeByName        | 不支持                                 |
40| 转场动画                                      | 支持                                  | 支持                                   |
41| 自定义转场动画                                | 支持                                  | 支持,动画类型受限                     |
42| 屏蔽转场动画                                  | 支持全局和单次                        | 支持 设置pageTransition方法duration为0 |
43| geometryTransition共享元素动画                | 支持(NavDestination之间共享)        | 不支持                                 |
44| 页面生命周期监听                              | UIObserver.on('navDestinationUpdate') | UIObserver.on('routerPageUpdate')      |
45| 获取页面栈对象                                | 支持                                  | 不支持                                 |
46| 路由拦截                                      | 支持通过setInercption做路由拦截       | 不支持                                 |
47| 路由栈信息查询                                | 支持                                  | getState() & getLength()               |
48| 路由栈move操作                                | moveToTop & moveIndexToTop            | 不支持                                 |
49| 沉浸式页面                                    | 支持                                  | 不支持,需通过window配置               |
50| 设置页面标题栏(titlebar)和工具栏(toolbar) | 支持                                  | 不支持                                 |
51| 模态嵌套路由                                  | 支持                                  | 不支持                                 |
52
53
54
55
56## 切换指导
57
58### 页面结构
59
60Router路由的页面是一个`@Entry`修饰的Component,每一个页面都需要在`main_page.json`中声明。
61
62```json
63// main_page.json
64{
65  "src": [
66    "pages/Index",
67    "pages/pageOne",
68    "pages/pageTwo"
69  ]
70}
71```
72
73以下为Router页面的示例。
74
75```ts
76// index.ets
77import { router } from '@kit.ArkUI';
78
79@Entry
80@Component
81
82struct Index {
83  @State message: string = 'Hello World';
84
85  build() {
86    Row() {
87      Column() {
88        Text(this.message)
89          .fontSize(50)
90          .fontWeight(FontWeight.Bold)
91        Button('router to pageOne', { stateEffect: true, type: ButtonType.Capsule })
92          .width('80%')
93          .height(40)
94          .margin(20)
95          .onClick(() => {
96            router.pushUrl({
97              url: 'pages/pageOne' // 目标url
98              }, router.RouterMode.Standard, (err) => {
99                if (err) {
100                  console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
101                  return;
102                }
103                console.info('Invoke pushUrl succeeded.');
104              })
105          })
106      }
107      .width('100%')
108    }
109    .height('100%')
110  }
111}
112```
113
114```ts
115// pageOne.ets
116import { router } from '@kit.ArkUI';
117
118@Entry
119@Component
120struct pageOne {
121  @State message: string = 'This is pageOne';
122
123  build() {
124    Row() {
125      Column() {
126        Text(this.message)
127          .fontSize(50)
128          .fontWeight(FontWeight.Bold)
129        Button('router back to Index', { stateEffect: true, type: ButtonType.Capsule })
130          .width('80%')
131          .height(40)
132          .margin(20)
133          .onClick(() => {
134            router.back();
135          })
136      }
137      .width('100%')
138    }
139    .height('100%')
140  }
141}
142```
143
144而基于Navigation的路由页面分为导航页和子页,导航页又叫Navbar,是Navigation包含的子组件,子页是NavDestination包含的子组件。
145
146以下为Navigation导航页的示例。
147
148```ts
149// index.ets
150@Entry
151@Component
152struct Index {
153  pathStack: NavPathStack = new NavPathStack()
154
155  build() {
156    Navigation(this.pathStack) {
157      Column() {
158        Button('Push PageOne', { stateEffect: true, type: ButtonType.Capsule })
159          .width('80%')
160          .height(40)
161          .margin(20)
162          .onClick(() => {
163            this.pathStack.pushPathByName('pageOne', null)
164          })
165      }.width('100%').height('100%')
166    }
167    .title("Navigation")
168    .mode(NavigationMode.Stack)
169  }
170}
171```
172以下为Navigation子页的示例。
173
174```ts
175// PageOne.ets
176
177@Builder
178export function PageOneBuilder() {
179  PageOne()
180}
181
182@Component
183export struct PageOne {
184  pathStack: NavPathStack = new NavPathStack()
185
186  build() {
187    NavDestination() {
188      Column() {
189        Button('回到首页', { stateEffect: true, type: ButtonType.Capsule })
190          .width('80%')
191          .height(40)
192          .margin(20)
193          .onClick(() => {
194            this.pathStack.clear()
195          })
196      }.width('100%').height('100%')
197    }.title('PageOne')
198    .onReady((context: NavDestinationContext) => {
199      this.pathStack = context.pathStack
200    })
201  }
202}
203```
204
205每个子页也需要配置到系统配置文件`route_map.json`中(参考[系统路由表](arkts-navigation-navigation.md#系统路由表))。
206
207```json
208// 工程配置文件module.json5中配置 {"routerMap": "$profile:route_map"}
209// route_map.json
210{
211  "routerMap": [
212    {
213      "name": "pageOne",
214      "pageSourceFile": "src/main/ets/pages/PageOne.ets",
215      "buildFunction": "PageOneBuilder",
216      "data": {
217        "description": "this is pageOne"
218      }
219    }
220  ]
221}
222```
223
224### 路由操作
225
226Router通过`@ohos.router`模块提供的方法来操作页面,使用前需要先`import`。
227
228```ts
229import { router } from '@kit.ArkUI';
230
231// push page
232router.pushUrl({ url:"pages/pageOne", params: null })
233
234// pop page
235router.back({ url: "pages/pageOne" })
236
237// replace page
238router.replaceUrl({ url: "pages/pageOne" })
239
240// clear all page
241router.clear()
242
243// 获取页面栈大小
244let size = router.getLength()
245
246// 获取页面状态
247let pageState = router.getState()
248```
249
250Navigation通过页面栈对象[NavPathStack](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md#navpathstack10)提供的方法来操作页面,需要创建一个栈对象并传入Navigation中。
251
252```ts
253@Entry
254@Component
255struct Index {
256  pathStack: NavPathStack = new NavPathStack()
257
258  build() {
259    // 设置NavPathStack并传入Navigation
260    Navigation(this.pathStack) {
261        // ...
262    }.width('100%').height('100%')
263    .title("Navigation")
264    .mode(NavigationMode.Stack)
265  }
266}
267
268
269// push page
270this.pathStack.pushPath({ name: 'pageOne' })
271
272// pop page
273this.pathStack.pop()
274this.pathStack.popToIndex(1)
275this.pathStack.popToName('pageOne')
276
277// replace page
278this.pathStack.replacePath({ name: 'pageOne' })
279
280// clear all page
281this.pathStack.clear()
282
283// 获取页面栈大小
284let size: number = this.pathStack.size()
285
286// 删除栈中name为PageOne的所有页面
287this.pathStack.removeByName("pageOne")
288
289// 删除指定索引的页面
290this.pathStack.removeByIndexes([1,3,5])
291
292// 获取栈中所有页面name集合
293this.pathStack.getAllPathName()
294
295// 获取索引为1的页面参数
296this.pathStack.getParamByIndex(1)
297
298// 获取PageOne页面的参数
299this.pathStack.getParamByName("pageOne")
300
301// 获取PageOne页面的索引集合
302this.pathStack.getIndexByName("pageOne")
303// ...
304```
305
306Router作为全局通用模块,可以在任意页面中调用,Navigation作为组件,子页面想要做路由需要拿到Navigation持有的页面栈对象NavPathStack,可以通过如下几种方式获取:
307
308**方式一**:通过`@Provide`和`@Consume`传递给子页面(有耦合,不推荐)。
309
310```ts
311// Navigation根容器
312@Entry
313@Component
314struct Index {
315  // Navigation创建一个Provide修饰的NavPathStack
316 @Provide('pathStack') pathStack: NavPathStack = new NavPathStack()
317
318  build() {
319    Navigation(this.pathStack) {
320        // ...
321    }
322    .title("Navigation")
323    .mode(NavigationMode.Stack)
324  }
325}
326
327// Navigation子页面
328@Component
329export struct PageOne {
330  // NavDestination通过Consume获取到
331  @Consume('pathStack') pathStack: NavPathStack;
332
333  build() {
334    NavDestination() {
335      // ...
336    }
337    .title("PageOne")
338  }
339}
340```
341
342**方式二**:子页面通过`OnReady`回调获取。
343
344```ts
345@Component
346export struct PageOne {
347  pathStack: NavPathStack = new NavPathStack()
348
349  build() {
350    NavDestination() {
351      // ...
352    }.title('PageOne')
353    .onReady((context: NavDestinationContext) => {
354      this.pathStack = context.pathStack
355    })
356  }
357}
358```
359
360**方式三**: 通过全局的`AppStorage`接口设置获取。
361
362```ts
363@Entry
364@Component
365struct Index {
366  pathStack: NavPathStack = new NavPathStack()
367
368  // 全局设置一个NavPathStack
369  aboutToAppear(): void {
370     AppStorage.setOrCreate("PathStack", this.pathStack)
371   }
372
373  build() {
374    Navigation(this.pathStack) {
375      // ...
376    }.title("Navigation")
377    .mode(NavigationMode.Stack)
378  }
379}
380
381// Navigation子页面
382@Component
383export struct PageOne {
384  // 子页面中获取全局的NavPathStack
385  pathStack: NavPathStack = AppStorage.get("PathStack") as NavPathStack
386
387  build() {
388    NavDestination() {
389      // ...
390    }
391    .title("PageOne")
392  }
393}
394```
395
396**方式四**:通过自定义组件查询接口获取,参考[queryNavigationInfo](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#querynavigationinfo12)。
397
398```ts
399import { uiObserver } from '@kit.ArkUI';
400
401// 子页面中的自定义组件
402@Component
403struct CustomNode {
404  pathStack : NavPathStack = new NavPathStack()
405
406  aboutToAppear() {
407    // query navigation info
408    let  navigationInfo : NavigationInfo = this.queryNavigationInfo() as NavigationInfo
409    this.pathStack = navigationInfo.pathStack;
410  }
411
412  build() {
413    Row() {
414      Button('跳转到PageTwo')
415        .onClick(()=>{
416          this.pathStack.pushPath({ name: 'pageTwo' })
417        })
418    }
419  }
420}
421```
422
423### 生命周期
424
425Router页面生命周期为`@Entry`页面中的通用方法,主要有如下四个生命周期:
426
427```ts
428// 页面创建后挂树的回调
429aboutToAppear(): void {
430}
431
432// 页面销毁前下树的回调
433aboutToDisappear(): void {
434}
435
436// 页面显示时的回调
437onPageShow(): void {
438}
439
440// 页面隐藏时的回调
441onPageHide(): void {
442}
443```
444
445其生命周期时序如下图所示:
446
447![image](figures/router_page_lifecycle.png)
448
449Navigation作为路由容器,其生命周期承载在NavDestination组件上,以组件事件的形式开放。
450具体生命周期描述请参考Navigation[页面生命周期](arkts-navigation-navigation.md#页面生命周期)。
451
452```ts
453@Component
454struct PageOne {
455
456  aboutToDisappear() {
457  }
458
459  aboutToAppear() {
460  }
461
462  build() {
463    NavDestination() {
464      // ...
465    }
466    .onWillAppear(()=>{
467    })
468    .onAppear(()=>{
469    })
470    .onWillShow(()=>{
471    })
472    .onShown(()=>{
473    })
474    .onWillHide(()=>{
475    })
476    .onHidden(()=>{
477    })
478    .onWillDisappear(()=>{
479    })
480    .onDisAppear(()=>{
481    })
482  }
483}
484```
485
486### 转场动画
487
488Router和Navigation都提供了系统的转场动画也提供了自定义转场的能力。
489
490其中Router自定义页面转场通过通用方法`pageTransition()`实现,具体可参考Router[页面转场动画](arkts-page-transition-animation.md)。
491
492Navigation作为路由容器组件,其内部的页面切换动画本质上属于组件跟组件之间的属性动画,可以通过Navigation中的[customNavContentTransition](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md#customnavcontenttransition11)事件提供自定义转场动画的能力,具体实现可以参考Navigation[自定义转场](arkts-navigation-navigation.md#自定义转场)。(注意:Dialog类型的页面当前没有转场动画)
493
494### 共享元素转场
495
496页面和页面之间跳转的时候需要进行共享元素过渡动画,Router可以通过通用属性`sharedTransition`来实现共享元素转场,具体可以参考如下链接:
497[Router共享元素转场动画](../reference/apis-arkui/arkui-ts/ts-transition-animation-shared-elements.md)。
498
499Navigation也提供了共享元素一镜到底的转场能力,需要配合`geometryTransition`属性,在子页面(NavDestination)之间切换时,可以实现共享元素转场,具体可参考[Navigation共享元素转场动画](arkts-navigation-navigation.md#共享元素转场)。
500
501### 跨包路由
502
503Router可以通过命名路由的方式实现跨包跳转。
504
5051. 在想要跳转到的共享包[HAR](../quick-start/har-package.md)或者[HSP](../quick-start/in-app-hsp.md)页面里,给@Entry修饰的自定义组件[EntryOptions](../quick-start/arkts-create-custom-components.md#entryoptions10)命名。
506
507   ```ts
508   // library/src/main/ets/pages/Index.ets
509   // library为新建共享包自定义的名字
510   @Entry({ routeName: 'myPage' })
511   @Component
512   export struct MyComponent {
513     build() {
514       Row() {
515         Column() {
516           Text('Library Page')
517             .fontSize(50)
518             .fontWeight(FontWeight.Bold)
519         }
520         .width('100%')
521       }
522       .height('100%')
523     }
524   }
525   ```
526
5272. 配置成功后需要在跳转的页面中引入命名路由的页面并跳转。
528
529   ```ts
530   import { router } from '@kit.ArkUI';
531   import { BusinessError } from '@kit.BasicServicesKit';
532   import('library/src/main/ets/pages/Index');  // 引入共享包中的命名路由页面
533
534   @Entry
535   @Component
536   struct Index {
537     build() {
538       Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
539         Text('Hello World')
540           .fontSize(50)
541           .fontWeight(FontWeight.Bold)
542           .margin({ top: 20 })
543           .backgroundColor('#ccc')
544           .onClick(() => { // 点击跳转到其他共享包中的页面
545             try {
546               router.pushNamedRoute({
547                 name: 'myPage',
548                 params: {
549                   data1: 'message',
550                   data2: {
551                     data3: [123, 456, 789]
552                   }
553                 }
554               })
555             } catch (err) {
556               let message = (err as BusinessError).message
557               let code = (err as BusinessError).code
558               console.error(`pushNamedRoute failed, code is ${code}, message is ${message}`);
559             }
560           })
561       }
562       .width('100%')
563       .height('100%')
564     }
565   }
566   ```
567
568Navigation作为路由组件,默认支持跨包跳转。
569
5701. 从HSP(HAR)中完成自定义组件(需要跳转的目标页面)开发,将自定义组件申明为export。
571
572   ```ts
573   @Component
574   export struct PageInHSP {
575     build() {
576       NavDestination() {
577           // ...
578       }
579     }
580   }
581   ```
582
5832. 在HSP(HAR)的index.ets中导出组件。
584
585   ```ts
586   export { PageInHSP } from "./src/main/ets/pages/PageInHSP"
587   ```
588
5893. 配置好HSP(HAR)的项目依赖后,在mainPage中导入自定义组件,并添加到pageMap中,即可正常调用。
590
591   ```
592   // 1.导入跨包的路由页面
593   import { PageInHSP } from 'library/src/main/ets/pages/PageInHSP'
594
595   @Entry
596   @Component
597   struct mainPage {
598    pageStack: NavPathStack = new NavPathStack()
599
600    @Builder pageMap(name: string) {
601      if (name === 'PageInHSP') {
602   	 // 2.定义路由映射表
603   	 PageInHSP()
604      }
605    }
606    build() {
607      Navigation(this.pageStack) {
608   	 Button("Push HSP Page")
609   	   .onClick(() => {
610   		  // 3.跳转到Hsp中的页面
611   		  this.pageStack.pushPath({ name: "PageInHSP"});
612   	 })
613      }
614      .mode(NavigationMode.Stack)
615      .navDestination(this.pageMap)
616    }
617   }
618   ```
619
620以上是通过**静态依赖**的形式完成了跨包的路由,在大型的项目中一般跨模块的开发需要解耦,那就需要依赖动态路由的能力。
621
622### 动态路由
623
624动态路由设计的目的是解决多个产品(Hap)之间可以复用相同的业务模块,各个业务模块之间解耦(模块之间跳转通过路由表跳转,不需要互相依赖)和路由功能扩展整合。
625
626业务特性模块对外暴露的就是模块内支持完成具体业务场景的多个页面的集合;路由管理就是将每个模块支持的页面都用统一的路由表结构管理起来。 当产品需要某个业务模块时,就会注册对应的模块的路由表。
627
628**动态路由的优势:**
629
6301. 路由定义除了跳转的URL以外,可以丰富的配置任意扩展信息,如横竖屏默认模式,是否需要鉴权等等,做路由跳转时的统一处理。
6312. 给每个路由设置一个名字,按照名称进行跳转而不是ets文件路径。
6323. 页面的加载可以使用动态Import(按需加载),防止首个页面加载大量代码导致卡顿。
633
634**Router实现动态路由主要有下面三个过程:**
635
6361. 定义过程: 路由表定义新增路由 -> 页面文件绑定路由名称(装饰器) -> 加载函数和页面文件绑定(动态import函数)<br>
6372. 定义注册过程: 路由注册(可在入口ability中按需注入依赖模块的路由表)。<br>
6383. 跳转过程: 路由表检查(是否注册过对应路由名称) -> 路由前置钩子(路由页面加载-动态Import) -> 路由跳转  -> 路由后置钩子(公共处理,如打点)。
639
640**Navigation实现动态路由有如下两种实现方案:**
641
642**方案一:** 自定义路由表
643
644基本实现跟上述Router动态路由类似。
6451. 开发者自定义路由管理模块,各个提供路由页面的模块均依赖此模块;
6462. 构建Navigation组件时,将NavPathStack注入路由管理模块,路由管理模块对NavPathStack进行封装,对外提供路由能力;
6473. 各个路由页面不再提供组件,转为提供@build封装的构建函数,并再通过WrappedBuilder封装后,实现全局封装;
6484. 各个路由页面将模块名称、路由名称、WrappedBuilder封装后构建函数注册如路由模块。
6495. 当路由需要跳转到指定路由时,路由模块完成对指定路由模块的动态导入,并完成路由跳转。
650
651具体的构建过程,可以参考Navigation[自动生成动态路由](https://gitee.com/harmonyos-cases/cases/blob/master/CommonAppDevelopment/common/routermodule/README_AUTO_GENERATE.md)示例。
652
653**方案二:** 系统路由表
654
655从API version 12版本开始,Navigation支持系统跨模块的路由表方案,整体设计是将路由表方案下沉到系统中管理,即在需要路由的各个业务模块(HSP/HAR)中独立配置`router_map.json`文件,在触发路由跳转时,应用只需要通过`NavPathStack`进行路由跳转,此时系统会自动完成路由模块的动态加载、组件构建,并完成路由跳转功能,从而实现了开发层面的模块解耦。
656具体可参考Navigation[系统路由表](arkts-navigation-navigation.md#系统路由表)。
657
658### 生命周期监听
659
660Router可以通过observer实现注册监听,接口定义请参考Router无感监听[observer.on('routerPageUpdate')](../reference/apis-arkui/js-apis-arkui-observer.md#observeronrouterpageupdate11)。
661
662
663```ts
664import { uiObserver } from '@kit.ArkUI';
665
666function callBackFunc(info: uiObserver.RouterPageInfo) {
667    console.info("RouterPageInfo is : " + JSON.stringify(info))
668}
669
670// used in ability context.
671uiObserver.on('routerPageUpdate', this.context, callBackFunc);
672
673// used in UIContext.
674uiObserver.on('routerPageUpdate', this.getUIContext(), callBackFunc);
675```
676
677在页面状态发生变化时,注册的回调将会触发,开发者可以通过回调中传入的入参拿到页面的相关信息,如:页面的名字,索引,路径,生命周期状态等。
678
679Navigation同样可以通过在observer中实现注册监听。
680
681```ts
682export default class EntryAbility extends UIAbility {
683  // ...
684  onWindowStageCreate(windowStage: window.WindowStage): void {
685    // ...
686    windowStage.getMainWindow((err: BusinessError, data) => {
687      // ...
688      windowClass = data;
689      // 获取UIContext实例。
690      let uiContext: UIContext = windowClass.getUIContext();
691      // 获取UIObserver实例。
692      let uiObserver : UIObserver = uiContext.getUIObserver();
693      // 注册DevNavigation的状态监听.
694      uiObserver.on("navDestinationUpdate",(info) => {
695        // NavDestinationState.ON_SHOWN = 0, NavDestinationState.ON_HIDE = 1
696        if (info.state == 0) {
697          // NavDestination组件显示时操作
698          console.info('page ON_SHOWN:' + info.name.toString());
699        }
700      })
701    })
702  }
703}
704```
705
706### 页面信息查询
707
708为了实现页面内自定义组件跟页面解耦,自定义组件中提供了全局查询页面信息的接口。
709
710Router可以通过[queryRouterPageInfo](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#queryrouterpageinfo12)接口查询当前自定义组件所在的Page页面的信息,其返回值包含如下几个属性,其中pageId是页面的唯一标识符:
711
712| 名称                 | 类型                        | 必填 | 说明                           |
713| -------------------- | --------------------------- | ---- | ------------------------------ |
714| context              | UIAbilityContext/ UIContext | 是   | routerPage页面对应的上下文信息 |
715| index                | number                      | 是   | routerPage在栈中的位置。       |
716| name                 | string                      | 是   | routerPage页面的名称。         |
717| path                 | string                      | 是   | routerPage页面的路径。         |
718| state                | RouterPageState             | 是   | routerPage页面的状态           |
719| pageId<sup>12+</sup> | string                      | 是   | routerPage页面的唯一标识       |
720
721```ts
722import { uiObserver } from '@kit.ArkUI';
723
724// 页面内的自定义组件
725@Component
726struct MyComponent {
727  aboutToAppear() {
728    let info: uiObserver.RouterPageInfo | undefined = this.queryRouterPageInfo();
729  }
730
731  build() {
732    // ...
733  }
734}
735```
736
737Navigation也可以通过[queryNavDestinationInfo](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#querynavdestinationinfo)接口查询当前自定义组件所在的NavDestination的信息,其返回值包含如下几个属性,其中navDestinationId是页面的唯一标识符:
738
739| 名称                          | 类型                | 必填 | 说明                                         |
740| ----------------------------- | ------------------- | ---- | -------------------------------------------- |
741| navigationId                  | ResourceStr         | 是   | 包含NavDestination组件的Navigation组件的id。 |
742| name                          | ResourceStr         | 是   | NavDestination组件的名称。                   |
743| state                         | NavDestinationState | 是   | NavDestination组件的状态。                   |
744| index<sup>12+<sup>            | number              | 是   | NavDestination在页面栈中的索引。             |
745| param<sup>12+<sup>            | Object              | 否   | NavDestination组件的参数。                   |
746| navDestinationId<sup>12+<sup> | string              | 是   | NavDestination组件的唯一标识ID。             |
747
748```ts
749import { uiObserver } from '@kit.ArkUI';
750
751@Component
752export struct NavDestinationExample {
753  build() {
754    NavDestination() {
755      MyComponent()
756    }
757  }
758}
759
760@Component
761struct MyComponent {
762  navDesInfo: uiObserver.NavDestinationInfo | undefined
763
764  aboutToAppear() {
765    this.navDesInfo = this.queryNavDestinationInfo();
766    console.log('get navDestinationInfo: ' + JSON.stringify(this.navDesInfo))
767  }
768
769  build() {
770    // ...
771  }
772}
773```
774
775### 路由拦截
776
777Router原生没有提供路由拦截的能力,开发者需要自行封装路由跳转接口,并在自己封装的接口中做路由拦截的判断并重定向路由。
778
779Navigation提供了[setInterception](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md#setinterception12)方法,用于设置Navigation页面跳转拦截回调。具体可以参考文档:Navigation[路由拦截](arkts-navigation-navigation.md#路由拦截)