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