# Router切æ¢Navigation 鉴于组件导航(Navigation)æ”¯æŒæ›´ä¸°å¯Œçš„动效ã€ä¸€æ¬¡å¼€å‘å¤šç«¯éƒ¨ç½²èƒ½åŠ›å’Œæ›´çµæ´»çš„æ ˆæ“作。本文主è¦ä»Žé¡µé¢è·³è½¬ã€åŠ¨æ•ˆå’Œç”Ÿå‘½å‘¨æœŸç‰æ–¹é¢ä»‹ç»å¦‚何从Router切æ¢åˆ°Navigation。 ## 页é¢ç»“æž„ Routerè·¯ç”±çš„é¡µé¢æ˜¯ä¸€ä¸ª`@Entry`修饰的Component,æ¯ä¸€ä¸ªé¡µé¢éƒ½éœ€è¦åœ¨`main_page.json`ä¸å£°æ˜Žã€‚ ```json // main_page.json { "src": [ "pages/Index", "pages/pageOne", "pages/pageTwo" ] } ``` 以下为Router页é¢çš„示例。 ```ts // index.ets import { router } from '@kit.ArkUI'; @Entry @Component struct Index { @State message: string = 'Hello World'; build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) Button('router to pageOne', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { router.pushUrl({ url: 'pages/pageOne' // ç›®æ ‡url }, router.RouterMode.Standard, (err) => { if (err) { console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`); return; } console.info('Invoke pushUrl succeeded.'); }) }) } .width('100%') } .height('100%') } } ``` ```ts // pageOne.ets import { router } from '@kit.ArkUI'; @Entry @Component struct pageOne { @State message: string = 'This is pageOne'; build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) Button('router back to Index', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { router.back(); }) } .width('100%') } .height('100%') } } ``` 而基于Navigation的路由页é¢åˆ†ä¸ºå¯¼èˆªé¡µå’Œå页,导航页åˆå«Navbar,是Navigation包å«çš„å组件,å页是NavDestination包å«çš„å组件。 以下为Navigation导航页的示例。 ```ts // index.ets @Entry @Component struct Index { pathStack: NavPathStack = new NavPathStack() build() { Navigation(this.pathStack) { Column() { Button('Push PageOne', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { this.pathStack.pushPathByName('pageOne', null) }) }.width('100%').height('100%') } .title("Navigation") .mode(NavigationMode.Stack) } } ``` 以下为Navigationå页的示例。 ```ts // PageOne.ets @Builder export function PageOneBuilder() { PageOne() } @Component export struct PageOne { pathStack: NavPathStack = new NavPathStack() build() { NavDestination() { Column() { Button('回到首页', { stateEffect: true, type: ButtonType.Capsule }) .width('80%') .height(40) .margin(20) .onClick(() => { this.pathStack.clear() }) }.width('100%').height('100%') }.title('PageOne') .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack }) } } ``` æ¯ä¸ªå页也需è¦é…置到系统é…置文件`route_map.json`ä¸ï¼ˆå‚考[系统路由表](arkts-navigation-navigation.md#系统路由表))。 ```json // 工程é…置文件module.json5ä¸é…ç½® {"routerMap": "$profile:route_map"} // route_map.json { "routerMap": [ { "name": "pageOne", "pageSourceFile": "src/main/ets/pages/PageOne.ets", "buildFunction": "PageOneBuilder", "data": { "description": "this is pageOne" } } ] } ``` ## 路由æ“作 Router通过`@ohos.router`æ¨¡å—æä¾›çš„æ–¹æ³•æ¥æ“作页é¢ï¼Œä½¿ç”¨å‰éœ€è¦å…ˆ`import`。 ```ts import { router } from '@kit.ArkUI'; // push page router.pushUrl({ url:"pages/pageOne", params: null }) // pop page router.back({ url: "pages/pageOne" }) // replace page router.replaceUrl({ url: "pages/pageOne" }) // clear all page router.clear() // 获å–页颿 ˆå¤§å° let size = router.getLength() // 获å–页é¢çŠ¶æ€ let pageState = router.getState() ``` Navigationé€šè¿‡é¡µé¢æ ˆå¯¹è±¡[NavPathStack](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md#navpathstack10)æä¾›çš„æ–¹æ³•æ¥æ“作页é¢ï¼Œéœ€è¦åˆ›å»ºä¸€ä¸ªæ ˆå¯¹è±¡å¹¶ä¼ å…¥Navigationä¸ã€‚ ```ts @Entry @Component struct Index { pathStack: NavPathStack = new NavPathStack() build() { // 设置NavPathStackå¹¶ä¼ å…¥Navigation Navigation(this.pathStack) { // ... }.width('100%').height('100%') .title("Navigation") .mode(NavigationMode.Stack) } } // push page this.pathStack.pushPath({ name: 'pageOne' }) // pop page this.pathStack.pop() this.pathStack.popToIndex(1) this.pathStack.popToName('pageOne') // replace page this.pathStack.replacePath({ name: 'pageOne' }) // clear all page this.pathStack.clear() // 获å–页颿 ˆå¤§å° let size: number = this.pathStack.size() // åˆ é™¤æ ˆä¸name为PageOneçš„æ‰€æœ‰é¡µé¢ this.pathStack.removeByName("pageOne") // åˆ é™¤æŒ‡å®šç´¢å¼•çš„é¡µé¢ this.pathStack.removeByIndexes([1, 3, 5]) // èŽ·å–æ ˆä¸æ‰€æœ‰é¡µé¢nameé›†åˆ this.pathStack.getAllPathName() // 获å–索引为1的页é¢å‚æ•° this.pathStack.getParamByIndex(1) // 获å–PageOne页é¢çš„傿•° this.pathStack.getParamByName("pageOne") // 获å–PageOne页é¢çš„ç´¢å¼•é›†åˆ this.pathStack.getIndexByName("pageOne") // ... ``` Router作为全局通用模å—,å¯ä»¥åœ¨ä»»æ„页é¢ä¸è°ƒç”¨ï¼ŒNavigation作为组件,å页颿ƒ³è¦åšè·¯ç”±éœ€è¦æ‹¿åˆ°NavigationæŒæœ‰çš„页颿 ˆå¯¹è±¡NavPathStack,å¯ä»¥é€šè¿‡å¦‚ä¸‹å‡ ç§æ–¹å¼èŽ·å–: **æ–¹å¼ä¸€**:通过`@Provide`å’Œ`@Consume`ä¼ é€’ç»™å页é¢ï¼ˆæœ‰è€¦åˆï¼Œä¸æŽ¨è)。 ```ts // Navigationæ ¹å®¹å™¨ @Entry @Component struct Index { // Navigation创建一个Provide修饰的NavPathStack @Provide('pathStack') pathStack: NavPathStack = new NavPathStack() build() { Navigation(this.pathStack) { // ... } .title("Navigation") .mode(NavigationMode.Stack) } } // Navigationåé¡µé¢ @Component export struct PageOne { // NavDestination通过Consume获å–到 @Consume('pathStack') pathStack: NavPathStack; build() { NavDestination() { // ... } .title("PageOne") } } ``` **æ–¹å¼äºŒ**:å页é¢é€šè¿‡`OnReady`回调获å–。 ```ts @Component export struct PageOne { pathStack: NavPathStack = new NavPathStack() build() { NavDestination() { // ... }.title('PageOne') .onReady((context: NavDestinationContext) => { this.pathStack = context.pathStack }) } } ``` **æ–¹å¼ä¸‰**: 通过全局的`AppStorage`接å£è®¾ç½®èŽ·å–。 ```ts @Entry @Component struct Index { pathStack: NavPathStack = new NavPathStack() // 全局设置一个NavPathStack aboutToAppear(): void { AppStorage.setOrCreate("PathStack", this.pathStack) } build() { Navigation(this.pathStack) { // ... }.title("Navigation") .mode(NavigationMode.Stack) } } // Navigationåé¡µé¢ @Component export struct PageOne { // å页é¢ä¸èŽ·å–全局的NavPathStack pathStack: NavPathStack = AppStorage.get("PathStack") as NavPathStack build() { NavDestination() { // ... } .title("PageOne") } } ``` **æ–¹å¼å››**:通过自定义组件查询接å£èŽ·å–,å‚考[queryNavigationInfo](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#querynavigationinfo12)。 ```ts // å页é¢ä¸çš„自定义组件 @Component struct CustomNode { pathStack: NavPathStack = new NavPathStack() aboutToAppear() { // query navigation info let navigationInfo: NavigationInfo = this.queryNavigationInfo() as NavigationInfo this.pathStack = navigationInfo.pathStack; } build() { Row() { Button('跳转到PageTwo') .onClick(() => { this.pathStack.pushPath({ name: 'pageTwo' }) }) } } } ``` ## 生命周期 Router页é¢ç”Ÿå‘½å‘¨æœŸä¸º`@Entry`页é¢ä¸çš„é€šç”¨æ–¹æ³•ï¼Œä¸»è¦æœ‰å¦‚下四个生命周期: ```ts // 页é¢åˆ›å»ºåŽæŒ‚æ ‘çš„å›žè°ƒ aboutToAppear(): void { } // 页é¢é”€æ¯å‰ä¸‹æ ‘的回调 aboutToDisappear(): void { } // 页颿˜¾ç¤ºæ—¶çš„回调 onPageShow(): void { } // 页é¢éšè—时的回调 onPageHide(): void { } ``` 其生命周期时åºå¦‚下图所示:  Navigation作为路由容器,其生命周期承载在NavDestination组件上,以组件事件的形å¼å¼€æ”¾ã€‚ 具体生命周期æè¿°è¯·å‚考Navigation[页é¢ç”Ÿå‘½å‘¨æœŸ](arkts-navigation-navigation.md#页é¢ç”Ÿå‘½å‘¨æœŸ)。 ```ts @Component struct PageOne { aboutToDisappear() { } aboutToAppear() { } build() { NavDestination() { // ... } .onWillAppear(() => { }) .onAppear(() => { }) .onWillShow(() => { }) .onShown(() => { }) .onWillHide(() => { }) .onHidden(() => { }) .onWillDisappear(() => { }) .onDisAppear(() => { }) } } ``` ## 转场动画 Routerå’ŒNavigation都æä¾›äº†ç³»ç»Ÿçš„转场动画也æä¾›äº†è‡ªå®šä¹‰è½¬åœºçš„能力。 å…¶ä¸Router自定义页é¢è½¬åœºé€šè¿‡é€šç”¨æ–¹æ³•`pageTransition()`实现,具体å¯å‚考Router[页é¢è½¬åœºåŠ¨ç”»](arkts-page-transition-animation.md)。 Navigation作为路由容器组件,其内部的页é¢åˆ‡æ¢åŠ¨ç”»æœ¬è´¨ä¸Šå±žäºŽç»„ä»¶è·Ÿç»„ä»¶ä¹‹é—´çš„å±žæ€§åŠ¨ç”»ï¼Œå¯ä»¥é€šè¿‡Navigationä¸çš„[customNavContentTransition](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md#customnavcontenttransition11)事件æä¾›è‡ªå®šä¹‰è½¬åœºåŠ¨ç”»çš„èƒ½åŠ›ï¼Œå…·ä½“å®žçŽ°å¯ä»¥å‚考Navigation[自定义转场](arkts-navigation-navigation.md#自定义转场)。(注æ„:Dialog类型的页é¢å½“剿²¡æœ‰è½¬åœºåŠ¨ç”»ï¼‰ ## å…±äº«å…ƒç´ è½¬åœº 页é¢å’Œé¡µé¢ä¹‹é—´è·³è½¬çš„æ—¶å€™éœ€è¦è¿›è¡Œå…±äº«å…ƒç´ 过渡动画,Routerå¯ä»¥é€šè¿‡é€šç”¨å±žæ€§`sharedTransition`æ¥å®žçŽ°å…±äº«å…ƒç´ è½¬åœºï¼Œå…·ä½“å¯ä»¥å‚考如下链接: [Routerå…±äº«å…ƒç´ è½¬åœºåŠ¨ç”»](../reference/apis-arkui/arkui-ts/ts-transition-animation-shared-elements.md)。 Navigation也æä¾›äº†å…±äº«å…ƒç´ 一镜到底的转场能力,需è¦é…åˆ`geometryTransition`属性,在å页é¢ï¼ˆNavDestinationï¼‰ä¹‹é—´åˆ‡æ¢æ—¶ï¼Œå¯ä»¥å®žçŽ°å…±äº«å…ƒç´ è½¬åœºï¼Œå…·ä½“å¯å‚考[Navigationå…±äº«å…ƒç´ è½¬åœºåŠ¨ç”»](arkts-navigation-navigation.md#å…±äº«å…ƒç´ è½¬åœº)。 ## 跨包路由 Routerå¯ä»¥é€šè¿‡å‘½å路由的方å¼å®žçŽ°è·¨åŒ…è·³è½¬ã€‚ 1. 在想è¦è·³è½¬åˆ°çš„共享包[HAR](../quick-start/har-package.md)或者[HSP](../quick-start/in-app-hsp.md)页é¢é‡Œï¼Œç»™@Entry修饰的自定义组件[EntryOptions](../quick-start/arkts-create-custom-components.md#entryoptions10)命å。 ```ts // 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%') } } ``` 2. é…ç½®æˆåŠŸåŽéœ€è¦åœ¨è·³è½¬çš„页é¢ä¸å¼•入命å路由的页é¢å¹¶è·³è½¬ã€‚ ```ts import { router } from '@kit.ArkUI'; import { BusinessError } from '@kit.BasicServicesKit'; import('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%') } } ``` Navigation作为路由组件,默认支æŒè·¨åŒ…跳转。 1. 从HSP(HAR)ä¸å®Œæˆè‡ªå®šä¹‰ç»„件(需è¦è·³è½¬çš„ç›®æ ‡é¡µé¢ï¼‰å¼€å‘,将自定义组件申明为export。 ```ts @Component export struct PageInHSP { build() { NavDestination() { // ... } } } ``` 2. 在HSP(HAR)的index.etsä¸å¯¼å‡ºç»„件。 ```ts export { PageInHSP } from "./src/main/ets/pages/PageInHSP" ``` 3. é…置好HSP(HAR)的项目ä¾èµ–åŽï¼Œåœ¨mainPageä¸å¯¼å…¥è‡ªå®šä¹‰ç»„ä»¶ï¼Œå¹¶æ·»åŠ åˆ°pageMapä¸ï¼Œå³å¯æ£å¸¸è°ƒç”¨ã€‚ ``` // 1.å¯¼å…¥è·¨åŒ…çš„è·¯ç”±é¡µé¢ import { PageInHSP } from 'library/src/main/ets/pages/PageInHSP' @Entry @Component struct mainPage { pageStack: NavPathStack = new NavPathStack() @Builder pageMap(name: string) { if (name === 'PageInHSP') { // 2.å®šä¹‰è·¯ç”±æ˜ å°„è¡¨ PageInHSP() } } build() { Navigation(this.pageStack) { Button("Push HSP Page") .onClick(() => { // 3.跳转到Hspä¸çš„é¡µé¢ this.pageStack.pushPath({ name: "PageInHSP" }); }) } .mode(NavigationMode.Stack) .navDestination(this.pageMap) } } ``` 以上是通过**陿€ä¾èµ–**的形å¼å®Œæˆäº†è·¨åŒ…的路由,在大型的项目ä¸ä¸€èˆ¬è·¨æ¨¡å—的开å‘需è¦è§£è€¦ï¼Œé‚£å°±éœ€è¦ä¾èµ–动æ€è·¯ç”±çš„能力。 ## 动æ€è·¯ç”± 动æ€è·¯ç”±è®¾è®¡çš„目的是解决多个产å“(Hap)之间å¯ä»¥å¤ç”¨ç›¸åŒçš„业务模å—,å„个业务模å—之间解耦(模å—之间跳转通过路由表跳转,ä¸éœ€è¦äº’相ä¾èµ–)和路由功能扩展整åˆã€‚ 业务特性模å—对外暴露的就是模å—内支æŒå®Œæˆå…·ä½“业务场景的多个页é¢çš„集åˆï¼›è·¯ç”±ç®¡ç†å°±æ˜¯å°†æ¯ä¸ªæ¨¡å—支æŒçš„页é¢éƒ½ç”¨ç»Ÿä¸€çš„路由表结构管ç†èµ·æ¥ã€‚ 当产å“éœ€è¦æŸä¸ªä¸šåŠ¡æ¨¡å—æ—¶ï¼Œå°±ä¼šæ³¨å†Œå¯¹åº”的模å—的路由表。 **动æ€è·¯ç”±çš„优势:** 1. 路由定义除了跳转的URL以外,å¯ä»¥ä¸°å¯Œçš„é…ç½®ä»»æ„æ‰©å±•ä¿¡æ¯ï¼Œå¦‚横竖å±é»˜è®¤æ¨¡å¼ï¼Œæ˜¯å¦éœ€è¦é‰´æƒç‰ç‰ï¼Œåšè·¯ç”±è·³è½¬æ—¶çš„统一处ç†ã€‚ 2. ç»™æ¯ä¸ªè·¯ç”±è®¾ç½®ä¸€ä¸ªåå—,按照åç§°è¿›è¡Œè·³è½¬è€Œä¸æ˜¯ets文件路径。 3. 页é¢çš„åŠ è½½å¯ä»¥ä½¿ç”¨åЍæ€Importï¼ˆæŒ‰éœ€åŠ è½½ï¼‰ï¼Œé˜²æ¢é¦–个页é¢åŠ è½½å¤§é‡ä»£ç 导致å¡é¡¿ã€‚ **Router实现动æ€è·¯ç”±ä¸»è¦æœ‰ä¸‹é¢ä¸‰ä¸ªè¿‡ç¨‹ï¼š** 1. 定义过程: 路由表定义新增路由 -> 页颿–‡ä»¶ç»‘定路由å称(装饰器) -> åŠ è½½å‡½æ•°å’Œé¡µé¢æ–‡ä»¶ç»‘定(动æ€import函数)<br> 2. 定义注册过程: 路由注册(å¯åœ¨å…¥å£ability䏿Œ‰éœ€æ³¨å…¥ä¾èµ–模å—的路由表)。<br> 3. 跳转过程: 路由表检查(æ˜¯å¦æ³¨å†Œè¿‡å¯¹åº”路由åç§°) -> 路由å‰ç½®é’©å(路由页é¢åŠ è½½-动æ€Import) -> 路由跳转 -> 路由åŽç½®é’©å(公共处ç†ï¼Œå¦‚打点)。 **Navigation实现动æ€è·¯ç”±æœ‰å¦‚下两ç§å®žçŽ°æ–¹æ¡ˆï¼š** **方案一:** 自定义路由表 基本实现跟上述Router动æ€è·¯ç”±ç±»ä¼¼ã€‚ 1. å¼€å‘è€…è‡ªå®šä¹‰è·¯ç”±ç®¡ç†æ¨¡å—,å„个æä¾›è·¯ç”±é¡µé¢çš„æ¨¡å—å‡ä¾èµ–æ¤æ¨¡å—ï¼› 2. 构建Navigation组件时,将NavPathStackæ³¨å…¥è·¯ç”±ç®¡ç†æ¨¡å—ï¼Œè·¯ç”±ç®¡ç†æ¨¡å—对NavPathStack进行å°è£…,对外æä¾›è·¯ç”±èƒ½åŠ›ï¼› 3. å„个路由页é¢ä¸å†æä¾›ç»„件,转为æä¾›@buildå°è£…的构建函数,并å†é€šè¿‡WrappedBuilderå°è£…åŽï¼Œå®žçް免局å°è£…ï¼› 4. å„个路由页é¢å°†æ¨¡å—åç§°ã€è·¯ç”±åç§°ã€WrappedBuilderå°è£…åŽæž„建函数注册如路由模å—。 5. 当路由需è¦è·³è½¬åˆ°æŒ‡å®šè·¯ç”±æ—¶ï¼Œè·¯ç”±æ¨¡å—完æˆå¯¹æŒ‡å®šè·¯ç”±æ¨¡å—的动æ€å¯¼å…¥ï¼Œå¹¶å®Œæˆè·¯ç”±è·³è½¬ã€‚ 具体的构建过程,å¯ä»¥å‚考Navigation[自动生æˆåЍæ€è·¯ç”±](https://gitee.com/harmonyos-cases/cases/blob/master/CommonAppDevelopment/common/routermodule/README_AUTO_GENERATE.md)示例。 **方案二:** 系统路由表 从API version 12版本开始,Navigation支æŒç³»ç»Ÿè·¨æ¨¡å—的路由表方案,整体设计是将路由表方案下沉到系统ä¸ç®¡ç†ï¼Œå³åœ¨éœ€è¦è·¯ç”±çš„å„个业务模å—(HSP/HAR)ä¸ç‹¬ç«‹é…ç½®`router_map.json`文件,在触å‘路由跳转时,应用åªéœ€è¦é€šè¿‡`NavPathStack`è¿›è¡Œè·¯ç”±è·³è½¬ï¼Œæ¤æ—¶ç³»ç»Ÿä¼šè‡ªåŠ¨å®Œæˆè·¯ç”±æ¨¡å—的动æ€åŠ è½½ã€ç»„件构建,并完æˆè·¯ç”±è·³è½¬åŠŸèƒ½ï¼Œä»Žè€Œå®žçŽ°äº†å¼€å‘层é¢çš„æ¨¡å—解耦。 具体å¯å‚考Navigation[系统路由表](arkts-navigation-navigation.md#系统路由表)。 ## ç”Ÿå‘½å‘¨æœŸç›‘å¬ Routerå¯ä»¥é€šè¿‡observer实现注册监å¬ï¼ŒæŽ¥å£å®šä¹‰è¯·å‚考Routeræ— æ„Ÿç›‘å¬[observer.on('routerPageUpdate')](../reference/apis-arkui/js-apis-arkui-observer.md#observeronrouterpageupdate11)。 ```ts import { uiObserver } from '@kit.ArkUI'; function callBackFunc(info: uiObserver.RouterPageInfo) { console.info("RouterPageInfo is : " + JSON.stringify(info)) } // used in ability context. uiObserver.on('routerPageUpdate', this.context, callBackFunc); // used in UIContext. uiObserver.on('routerPageUpdate', this.getUIContext(), callBackFunc); ``` 在页é¢çжæ€å‘生å˜åŒ–时,注册的回调将会触å‘,开å‘者å¯ä»¥é€šè¿‡å›žè°ƒä¸ä¼ å…¥çš„å…¥å‚æ‹¿åˆ°é¡µé¢çš„相关信æ¯ï¼Œå¦‚:页é¢çš„åå—,索引,路径,生命周期状æ€ç‰ã€‚ NavigationåŒæ ·å¯ä»¥é€šè¿‡åœ¨observerä¸å®žçŽ°æ³¨å†Œç›‘å¬ã€‚ ```ts // EntryAbility.ets import { BusinessError } from '@kit.BasicServicesKit'; import { UIObserver } from '@kit.ArkUI'; export default class EntryAbility extends UIAbility { // ... onWindowStageCreate(windowStage: window.WindowStage): void { // ... windowStage.getMainWindow((err: BusinessError, data) => { // ... let windowClass = data; // 获å–UIContext实例。 let uiContext: UIContext = windowClass.getUIContext(); // 获å–UIObserver实例。 let uiObserver : UIObserver = uiContext.getUIObserver(); // 注册DevNavigation的状æ€ç›‘å¬. uiObserver.on("navDestinationUpdate",(info) => { // NavDestinationState.ON_SHOWN = 0, NavDestinationState.ON_HIDE = 1 if (info.state == 0) { // NavDestination组件显示时æ“作 console.info('page ON_SHOWN:' + info.name.toString()); } }) }) } } ``` ## 页é¢ä¿¡æ¯æŸ¥è¯¢ 为了实现页é¢å†…自定义组件跟页é¢è§£è€¦ï¼Œè‡ªå®šä¹‰ç»„ä»¶ä¸æä¾›äº†å…¨å±€æŸ¥è¯¢é¡µé¢ä¿¡æ¯çš„æŽ¥å£ã€‚ Routerå¯ä»¥é€šè¿‡[queryRouterPageInfo](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#queryrouterpageinfo12)æŽ¥å£æŸ¥è¯¢å½“å‰è‡ªå®šä¹‰ç»„件所在的Page页é¢çš„ä¿¡æ¯ï¼Œå…¶è¿”回值包å«å¦‚ä¸‹å‡ ä¸ªå±žæ€§ï¼Œå…¶ä¸pageId是页é¢çš„å”¯ä¸€æ ‡è¯†ç¬¦ï¼š | åç§° | 类型 | å¿…å¡« | 说明 | | -------------------- | --------------------------- | ---- | ------------------------------ | | context | UIAbilityContext/ UIContext | 是 | routerPage页é¢å¯¹åº”çš„ä¸Šä¸‹æ–‡ä¿¡æ¯ | | index | number | 是 | routerPageåœ¨æ ˆä¸çš„ä½ç½®ã€‚ | | name | string | 是 | routerPage页é¢çš„å称。 | | path | string | 是 | routerPage页é¢çš„路径。 | | state | RouterPageState | 是 | routerPage页é¢çš„çŠ¶æ€ | | pageId<sup>12+</sup> | string | 是 | routerPage页é¢çš„å”¯ä¸€æ ‡è¯† | ```ts import { uiObserver } from '@kit.ArkUI'; // 页é¢å†…的自定义组件 @Component struct MyComponent { aboutToAppear() { let info: uiObserver.RouterPageInfo | undefined = this.queryRouterPageInfo(); } build() { // ... } } ``` Navigation也å¯ä»¥é€šè¿‡[queryNavDestinationInfo](../reference/apis-arkui/arkui-ts/ts-custom-component-api.md#querynavdestinationinfo)æŽ¥å£æŸ¥è¯¢å½“å‰è‡ªå®šä¹‰ç»„件所在的NavDestination的信æ¯ï¼Œå…¶è¿”回值包å«å¦‚ä¸‹å‡ ä¸ªå±žæ€§ï¼Œå…¶ä¸navDestinationId是页é¢çš„å”¯ä¸€æ ‡è¯†ç¬¦ï¼š | åç§° | 类型 | å¿…å¡« | 说明 | | ----------------------------- | ------------------- | ---- | -------------------------------------------- | | navigationId | ResourceStr | 是 | 包å«NavDestination组件的Navigation组件的id。 | | name | ResourceStr | 是 | NavDestination组件的å称。 | | state | NavDestinationState | 是 | NavDestination组件的状æ€ã€‚ | | index<sup>12+<sup> | number | 是 | NavDestinationåœ¨é¡µé¢æ ˆä¸çš„索引。 | | param<sup>12+<sup> | Object | å¦ | NavDestinationç»„ä»¶çš„å‚æ•°ã€‚ | | navDestinationId<sup>12+<sup> | string | 是 | NavDestinationç»„ä»¶çš„å”¯ä¸€æ ‡è¯†ID。 | ```ts import { uiObserver } from '@kit.ArkUI'; @Component export struct NavDestinationExample { build() { NavDestination() { MyComponent() } } } @Component struct MyComponent { navDesInfo: uiObserver.NavDestinationInfo | undefined aboutToAppear() { this.navDesInfo = this.queryNavDestinationInfo(); console.log('get navDestinationInfo: ' + JSON.stringify(this.navDesInfo)) } build() { // ... } } ``` ## 路由拦截 Router原生没有æä¾›è·¯ç”±æ‹¦æˆªçš„能力,开å‘者需è¦è‡ªè¡Œå°è£…路由跳转接å£ï¼Œå¹¶åœ¨è‡ªå·±å°è£…的接å£ä¸åšè·¯ç”±æ‹¦æˆªçš„判æ–å¹¶é‡å®šå‘路由。 Navigationæä¾›äº†[setInterception](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md#setinterception12)方法,用于设置Navigation页é¢è·³è½¬æ‹¦æˆªå›žè°ƒã€‚具体å¯ä»¥å‚考文档:Navigation[路由拦截](arkts-navigation-navigation.md#路由拦截)