• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  ![createHsp.png](../screenshots/device/createHsp.png)
150- 选择module为**Shared Library**类型的Hsp模块。
151  ![createHsp2.png](../screenshots/device/createHsp2.png)
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   ![compileHsp.png](../screenshots/device/compileHsp.png)
173
1744. 运行时,需要在运行模块处在Ide的工具栏窗口,点击“**Run** > **Edit Configurations** ”,配置edit Configuration,如下图示。
175   ![run1.png](../screenshots/device/run1.png)
176- 勾选**Deploy Multi Hap Packages**进行混合编译,即可运行。[详细步骤参考](https://docs.openharmony.cn/pages/v4.0/zh-cn/application-dev/quick-start/in-app-hsp.md/)
177   ![run2.png](../screenshots/device/run2.png)
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 ![shopping.gif](../screenshots/device/shopping.gif)
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)