1# Navigation开发示例应用 2 3## 简介 4 5在应用开发时,我们常常遇到,需要在应用内多页面跳转场景时中使用`Navigation`导航组件做统一的页面跳转管理,它提供了一系列属性方法来设置页面的标题栏、工具栏以及菜单栏的各种展示样式。除此之外还拥有动态加载,NavPathStack路由跳转,跨包引用Hsp等能力。 6 7本文就以Navigation开发示例应用为例,来展开讲解Navigation以上的技术点,帮助开发者快速学习。 8 9## 场景概述 10 11ArkUI中,应用内导航组件Navigation一般作为Page页面的根容器,Navigation组件主要包含主页和内容页。 12 13主页由标题栏、内容区和工具栏组成,其中内容区默认首页显示导航内容(Navigation的子组件) 或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。 14 15Navigation的路由切换的方式有两种,本次示例主要介绍NavPathStack的使用。 16 17* 在API Version 9上,首页导航内容需要配合NavRouter组件实现页面路由。 18* 从API Version 10开始,首页推荐使用NavPathStack配合NavDestination属性进行页面路由。 19 20> 通过本篇文章的学习,你将学会: 21> 22> 1.如何使用**NavPathStack路由转场** 23> 24> 2.如何在**Navigation中跨包引用Hsp** 25> 26> 3.如何在**Navigation中使用动态加载** 27 28## Router场景与Navigation适用场景对比 29 30| 组件 | 适用场景 | 特点 | 转场动画效果对比 | 31|-----|------|-------------------|----------| 32| Router | 模块间与模块内页面切换 | 通过每个页面的url实现模块间解耦 | 页面平推转场效果 | 33| Navigation | 模块内页面切换 | 通过组件级路由统一路由管理 | 向右折叠转场效果 | 34 35## 使用NavPathStack路由转场 36NavPathStack是Navigation路由栈,通过对栈内元素的操作,完成页面的路由转场。详细API如下表, [详细API说明文档](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md): 37 38| API | 描述 | 39| --------------- | ----------------------------------------------------------- | 40| pushPath | 将info指定的NavDestination页面信息入栈。 | 41| pushPathByName | 将name指定的NavDestination页面信息入栈,传递的数据为param。 | 42| pop | 弹出路由栈栈顶元素。 | 43| popToName | 回退路由栈到第一个名为name的NavDestination页面。 | 44| popToIndex | 回退路由栈到index指定的NavDestination页面。 | 45| moveToTop | 将第一个名为name的NavDestination页面移到栈顶。 | 46| moveIndexToTop | 将index指定的NavDestination页面移到栈顶。 | 47| clear | 清除栈中所有页面。 | 48| getAllPathName | 获取栈中所有NavDestination页面的名称。 | 49| getParamByIndex | 获取index指定的NavDestination页面的参数信息。 | 50| getParamByName | 获取全部名为name的NavDestination页面的参数信息。 | 51| getIndexByName | 获取全部名为name的NavDestination页面的位置索引。 | 52 53 54 55### 实现思路 56 57NavPathStack通过pushPath跳转页面,通过pop返回: 581. 通过pushPath跳转,如” **主页** > **商品详情页** “,源码参考[DetailPage.ets](../feature/detailPageHsp/src/main/ets/main/DetailPage.ets) 59 60``` 61this.pageStack.pushPath({ name: 'GoodsDetailView', param: item }) 62``` 63 642. NavPathStack通过pop返回,从” **详情页** > **返回到主页** “,源码参考[Detail.ets](../entry/src/main/ets/pages/Detail.ets) 65 66``` 67.onBackPressed(() => { 68 this.pageStack.pop(); 69 return true; 70}) 71``` 72 73### 开发步骤 74 751. 在pageMap组件中定义需要用到的页面,定义NavPathStack对象,并用@provide传递给全部子组件,在entry模块的Home页面build()中,定义Navigation容器并设置navDestination()属性加载PageMap组件,并将需要使用容器的组件引入并调用,[源码参考](../entry/src/main/ets/pages/Home.ets) 76 77```javascript 78import { NavigationHomePage } from '@ohos/navigation-component'; 79 80@Provide('pageStack') pageStack: NavPathStack = new NavPathStack(); 81 82@Builder 83PageMap(name: string, param: NavPathStack) { 84 if (name === 'DetailPage') { 85 // 商品列表详情页 86 this.detailPageLoader(); 87 } else if (name === 'SetPage') { 88 // 设置页 89 SetPage() 90 } else if (name === "Live") { 91 // 直播页 92 Live() 93 } 94} 95 96build() { 97 Navigation(this.pageStack) { 98 NavigationHomePage(); 99 } 100 .hideTitleBar(true) 101 .navDestination(this.PageMap) 102} 103``` 104 1052. 在NavigationHomePage中定义NavDestination并包括需要被加载的组件,[源码参考](../feature/navigationHome/src/main/ets/main/NavigationHomePage.ets) 106 107```javascript 108export struct NavigationHomePage { 109 110NavDestination() { 111 MainPage() 112 } 113} 114``` 115 1163. 在DetailPage中@Consume引入pageStack,通过NavPathStack的api触发切换组件,[源码参考](../feature/detailPageHsp/src/main/ets/main/DetailPage.ets) 117 118```javascript 119@Consume('pageStack') pageStack: NavPathStack; 120 121.onClick(() => { 122 this.pageStack.pushPath({ name: 'GoodsDetailView', param: item }) 123 }) 124``` 125 1264. 在Detail中,通过pop出栈,返回前页,[源码参考](../entry/src/main/ets/pages/Detail.ets) 127 128```javascript 129@Consume('pageStack') pageStack: NavPathStack; 130.onBackPressed(() => { 131 this.pageStack.pop(); 132 return true; 133}) 134``` 135 136## Navigation中跨包引用Hsp 137 138本示例以创建一个Hsp包detailPageHsp模块为例,并介绍如何混合编译工程[Hsp包介绍及详细操作步骤](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/quick-start/in-app-hsp.md/) 139 140### 实现思路 141 142创建一个Hsp类型的detailPageHsp模块,并在entry中引用创建的Hsp模块。 143 144### 开发步骤 145 1461. 创建Hsp模块。 147- 在根目录右键新创建module为**Shared Library**类型的Hsp模块,并将模块命名为detailPageHsp并拖拽至feature文件夹下做包的统一管理,如下图示; 148 149  150- 选择module为**Shared Library**类型的Hsp模块。 151  152 153 1542. 定义Hsp出口:在创建后的Hsp包内编写业务代码,并在index.ets中export组件。[源码参考](../feature/detailPageHsp/Index.ets); 155* 引用方如何使用Hsp:entry模块通过在oh-package.json5文件中加入定义的Hsp依赖。[源码参考](../entry/oh-package.json5); 156```javascript 157"dependencies": { 158 "@ohos/details-page-hsp": "file:../feature/detailPageHsp", 159} 160``` 161* Hap中使用:在组件中引入依赖。[源码参考](../entry/src/main/ets/pages/Detail.ets); 162```javascript 163import { DetailPage } from '@ohos/details-page-hsp'; 164 165build(){ 166 NavDestination() { 167 DetailPage(); 168 } 169} 170``` 1713. 编译时,需选中detailPageHsp模块,在ide的工具栏窗口,点击“**Build** > **Make Module 'detailPageHsp'** ”,进行编译构建,生成Hsp,如下图示。 172  173 1744. 运行时,需要在运行模块处在Ide的工具栏窗口,点击“**Run** > **Edit Configurations** ”,配置edit Configuration,如下图示。 175  176- 勾选**Deploy Multi Hap Packages**进行混合编译,即可运行。[详细步骤参考](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/quick-start/in-app-hsp.md/) 177  178 179 180 181## Navigation中使用动态加载 182 183* 本示例通过定义一个需要被动态加载的组件DetailPage,配合Navigation实现动态加载示例的演示。源码参考[DetailPage.ets](../feature/detailPageHsp/src/main/ets/main/DetailPage.ets); 184 185### 实现思路 186 187* 定义一个DynamicLoader动态回调类作为容器,用来注册和调用动态加载函数。源码参考[DynamicLoader.ets](../feature/navigationHome/src/main/ets/common/DynamicLoader.ets); 188* 将DetailPage组件用DetailPageLoader函数封装,当DetailPageLoader被调用时,会渲染DetailPage页面。源码参考[DetailPageLoader.ets](../entry/src/main/ets/pages/DetailPageLoader.ets); 189* 在主页实现动态加载DetailPage的步骤如下: 190 由于navDestination无法直接动态import组件(import是函数,组件中无法引用函数),此处采用声明@BuilderParam detailPageLoader函数,在点击时初始化此函数,此时navDestination中可以调用this.detailPageLoader()从而加载组件DetailPage。 191 192### 开发步骤 193 1941. 主页Home中定义组件加载函数@BuilderParam detailPageLoader: () => void,用来承接await import异步导入detailPageLoader的结果。源码参考[Home.ets](../entry/src/main/ets/pages/Home.ets) 195```javascript 196@BuilderParam detailPageLoader: () => void 197``` 1982. 注册异步函数,点击时为detailPageLoader初始化,当满足key为DetailPage时,此时异步的加载DetailPageLoader,渲染DetailPage,源码参考[Home.ets](../entry/src/main/ets/pages/Home.ets) 199```javascript 200DynamicLoader.getInstance().register( 201async (key: string) => { 202 if (key === "DetailPage") { 203 let obj = await import("./DetailPageLoader"); 204 this.detailPageLoader = obj.DetailPageLoader; 205 } 206}) 207 ``` 2083. 定义NavDestination中动态加载函数,当存在跳转行为时,会调用此函数,源码参考[Home.ets](../entry/src/main/ets/pages/Home.ets) 209```javascript 210PageMap(name: string, param: NavPathStack) { 211 if (name === 'DetailPage') {this.detailPageLoader();}) 212``` 2134. 按钮触发点击函数,调用detailPageLoader,此时真正的初始化@BuilderParam detailPageLoader,并通过Navigation中PageMap动态加载组件DetailPage,源码参考[GoodsList.ets](../feature/navigationHome/src/main/ets/components/good/GoodsList.ets) 214```javascript 215Column() {} 216 .onClick(() => { 217 // 动态加载组件 218 DynamicLoader.getInstance().fire('DetailPage').then(()=>{ 219 this.active = true; 220 this.pageStack.pushPathByName('DetailPage', item); 221 }) 222}) 223 ``` 224 225 226## 运行效果 227 228  229 230 231## 参考文档 232 233[1] [桔子购物sample · OpenHarmony - Gitee.com](https://gitee.com/openharmony/applications_app_samples/tree/master/code/Solutions/Shopping/OrangeShopping) 234 235[2] [Navigation组件 · OpenHarmony/docs - Gitee.com](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md)