• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 页面路由
2
3
4页面路由指在应用程序中实现不同页面之间的跳转和数据传递。OpenHarmony提供了Router模块,通过不同的url地址,可以方便地进行页面路由,轻松地访问不同的页面。本文将从[页面跳转](#页面跳转)、[页面返回](#页面返回)和[页面返回前增加一个询问框](#页面返回前增加一个询问框)几个方面介绍Router模块提供的功能。
5
6
7## 页面跳转
8
9页面跳转是开发过程中的一个重要组成部分。在使用应用程序时,通常需要在不同的页面之间跳转,有时还需要将数据从一个页面传递到另一个页面。
10
11  **图1** 页面跳转
12![router-jump-to-detail](figures/router-jump-to-detail.gif)
13
14Router模块提供了两种跳转模式,分别是[router.pushUrl()](../reference/apis/js-apis-router.md#routerpushurl9)和[router.replaceUrl()](../reference/apis/js-apis-router.md#routerreplaceurl9)。这两种模式决定了目标页面是否会替换当前页。
15
16- router.pushUrl():目标页面不会替换当前页,而是压入[页面栈](../application-models/page-mission-stack.md)。这样可以保留当前页的状态,并且可以通过返回键或者调用[router.back()](../reference/apis/js-apis-router.md#routerback)方法返回到当前页。
17
18- router.replaceUrl():目标页面会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。
19
20>**说明:**
21>
22>页面栈的最大容量为32个页面。如果超过这个限制,可以调用[router.clear()](../reference/apis/js-apis-router.md#routerclear)方法清空历史页面栈,释放内存空间。
23
24同时,Router模块提供了两种实例模式,分别是Standard和Single。这两种模式决定了目标url是否会对应多个实例。
25
26- Standard:多实例模式,也是默认情况下的跳转模式。目标页面会被添加到页面栈顶,无论栈中是否存在相同url的页面。
27
28- Single:单实例模式。如果目标页面的url已经存在于页面栈中,则会将离栈顶最近的同url页面移动到栈顶,该页面成为新建页。如果目标页面的url在页面栈中不存在同url页面,则按照默认的多实例模式进行跳转。
29
30在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
31
32
33```ts
34import router from '@ohos.router';
35```
36
37- 场景一:有一个主页(Home)和一个详情页(Detail),希望从主页点击一个商品,跳转到详情页。同时,需要保留主页在页面栈中,以便返回时恢复状态。这种场景下,可以使用pushUrl()方法,并且使用Standard实例模式(或者省略)。
38
39
40  ```ts
41  // 在Home页面中
42  function onJumpClick(): void {
43    router.pushUrl({
44      url: 'pages/Detail' // 目标url
45    }, router.RouterMode.Standard, (err) => {
46      if (err) {
47        console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
48        return;
49      }
50      console.info('Invoke pushUrl succeeded.');
51    });
52  }
53  ```
54
55  >**说明:**
56  >
57  >多实例模式下,router.RouterMode.Standard参数可以省略。
58
59- 场景二:有一个登录页(Login)和一个个人中心页(Profile),希望从登录页成功登录后,跳转到个人中心页。同时,销毁登录页,在返回时直接退出应用。这种场景下,可以使用replaceUrl()方法,并且使用Standard实例模式(或者省略)。
60
61
62  ```ts
63  // 在Login页面中
64  function onJumpClick(): void {
65    router.replaceUrl({
66      url: 'pages/Profile' // 目标url
67    }, router.RouterMode.Standard, (err) => {
68      if (err) {
69        console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
70        return;
71      }
72      console.info('Invoke replaceUrl succeeded.');
73    })
74  }
75  ```
76
77  >**说明:**
78  >
79  >多实例模式下,router.RouterMode.Standard参数可以省略。
80
81- 场景三:有一个设置页(Setting)和一个主题切换页(Theme),希望从设置页点击主题选项,跳转到主题切换页。同时,需要保证每次只有一个主题切换页存在于页面栈中,在返回时直接回到设置页。这种场景下,可以使用pushUrl()方法,并且使用Single实例模式。
82
83
84  ```ts
85  // 在Setting页面中
86  function onJumpClick(): void {
87    router.pushUrl({
88      url: 'pages/Theme' // 目标url
89    }, router.RouterMode.Single, (err) => {
90      if (err) {
91        console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
92        return;
93      }
94      console.info('Invoke pushUrl succeeded.');
95    });
96  }
97  ```
98
99- 场景四:有一个搜索结果列表页(SearchResult)和一个搜索结果详情页(SearchDetail),希望从搜索结果列表页点击某一项结果,跳转到搜索结果详情页。同时,如果该结果已经被查看过,则不需要再新建一个详情页,而是直接跳转到已经存在的详情页。这种场景下,可以使用replaceUrl()方法,并且使用Single实例模式。
100
101
102  ```ts
103  // 在SearchResult页面中
104  function onJumpClick(): void {
105    router.replaceUrl({
106      url: 'pages/SearchDetail' // 目标url
107    }, router.RouterMode.Single, (err) => {
108      if (err) {
109        console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
110        return;
111      }
112      console.info('Invoke replaceUrl succeeded.');})
113  }
114  ```
115
116以上是不带参数传递的场景。
117
118如果需要在跳转时传递一些数据给目标页面,则可以在调用Router模块的方法时,添加一个params属性,并指定一个对象作为参数。例如:
119
120
121```ts
122class DataModelInfo {
123  age: number;
124}
125
126class DataModel {
127  id: number;
128  info: DataModelInfo;
129}
130
131function onJumpClick(): void {
132  // 在Home页面中
133  let paramsInfo: DataModel = {
134    id: 123,
135    info: {
136      age: 20
137    }
138  };
139
140  router.pushUrl({
141    url: 'pages/Detail', // 目标url
142    params: paramsInfo // 添加params属性,传递自定义参数
143  }, (err) => {
144    if (err) {
145      console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
146      return;
147    }
148    console.info('Invoke pushUrl succeeded.');
149  })
150}
151```
152
153在目标页面中,可以通过调用Router模块的[getParams()](../reference/apis/js-apis-router.md#routergetparams)方法来获取传递过来的参数。例如:
154
155
156```ts
157const params = router.getParams(); // 获取传递过来的参数对象
158const id = params['id']; // 获取id属性的值
159const age = params['info'].age; // 获取age属性的值
160```
161
162
163## 页面返回
164
165当用户在一个页面完成操作后,通常需要返回到上一个页面或者指定页面,这就需要用到页面返回功能。在返回的过程中,可能需要将数据传递给目标页面,这就需要用到数据传递功能。
166
167  **图2** 页面返回  
168
169![router-back-to-home](figures/router-back-to-home.gif)
170
171在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
172
173
174```ts
175import router from '@ohos.router';
176```
177
178可以使用以下几种方式进行页面返回:
179
180- 方式一:返回到上一个页面。
181
182
183  ```ts
184  router.back();
185  ```
186
187  这种方式会返回到上一个页面,即上一个页面在页面栈中的位置。但是,上一个页面必须存在于页面栈中才能够返回,否则该方法将无效。
188
189- 方式二:返回到指定页面。
190
191
192  ```ts
193  router.back({
194    url: 'pages/Home'
195  });
196  ```
197
198  这种方式可以返回到指定页面,需要指定目标页面的路径。目标页面必须存在于页面栈中才能够返回。
199
200- 方式三:返回到指定页面,并传递自定义参数信息。
201
202
203  ```ts
204  router.back({
205    url: 'pages/Home',
206    params: {
207      info: '来自Home页'
208    }
209  });
210  ```
211
212  这种方式不仅可以返回到指定页面,还可以在返回的同时传递自定义参数信息。这些参数信息可以在目标页面中通过调用router.getParams()方法进行获取和解析。
213
214在目标页面中,在需要获取参数的位置调用router.getParams()方法即可,例如在onPageShow()生命周期回调中:
215
216
217```ts
218onPageShow() {
219  const params = router.getParams(); // 获取传递过来的参数对象
220  const info = params['info']; // 获取info属性的值
221}
222```
223
224>**说明:**
225>
226>当使用router.back()方法返回到指定页面时,该页面会被重新压入栈顶,而原栈顶页面(包括)到指定页面(不包括)之间的所有页面栈都将被销毁。
227>
228> 另外,如果使用router.back()方法返回到原来的页面,原页面不会被重复创建,因此使用\@State声明的变量不会重复声明,也不会触发页面的aboutToAppear()生命周期回调。如果需要在原页面中使用返回页面传递的自定义参数,可以在需要的位置进行参数解析。例如,在onPageShow()生命周期回调中进行参数解析。
229
230
231## 页面返回前增加一个询问框
232
233在开发应用时,为了避免用户误操作或者丢失数据,有时候需要在用户从一个页面返回到另一个页面之前,弹出一个询问框,让用户确认是否要执行这个操作。
234
235本文将从[系统默认询问框](#系统默认询问框)和[自定义询问框](#自定义询问框)两个方面来介绍如何实现页面返回前增加一个询问框的功能。
236
237  **图3** 页面返回前增加一个询问框  
238
239![router-add-query-box-before-back](figures/router-add-query-box-before-back.gif)
240
241
242### 系统默认询问框
243
244为了实现这个功能,可以使用页面路由Router模块提供的两个方法:[router.showAlertBeforeBackPage()](../reference/apis/js-apis-router.md#routershowalertbeforebackpage9)和[router.back()](../reference/apis/js-apis-router.md#routerback)来实现这个功能。
245
246在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
247
248
249```ts
250import router from '@ohos.router';
251```
252
253如果想要在目标界面开启页面返回询问框,需要在调用[router.back()](../reference/apis/js-apis-router.md#routerback)方法之前,通过调用[router.showAlertBeforeBackPage()](../reference/apis/js-apis-router.md#routershowalertbeforebackpage9)方法设置返回询问框的信息。例如,在支付页面中定义一个返回按钮的点击事件处理函数:
254
255
256```ts
257// 定义一个返回按钮的点击事件处理函数
258function onBackClick(): void {
259  // 调用router.showAlertBeforeBackPage()方法,设置返回询问框的信息
260  try {
261    router.showAlertBeforeBackPage({
262      message: '您还没有完成支付,确定要返回吗?' // 设置询问框的内容
263    });
264  } catch (err) {
265    console.error(`Invoke showAlertBeforeBackPage failed, code is ${err.code}, message is ${err.message}`);
266  }
267
268  // 调用router.back()方法,返回上一个页面
269  router.back();
270}
271```
272
273其中,router.showAlertBeforeBackPage()方法接收一个对象作为参数,该对象包含以下属性:
274
275message:string类型,表示询问框的内容。
276
277如果调用成功,则会在目标界面开启页面返回询问框;如果调用失败,则会抛出异常,并通过err.codeerr.message获取错误码和错误信息。
278
279当用户点击“返回”按钮时,会弹出确认对话框,询问用户是否确认返回。选择“取消”将停留在当前页目标页面;选择“确认”将触发router.back()方法,并根据参数决定如何执行跳转。
280
281### 自定义询问框
282
283自定义询问框的方式,可以使用[弹窗](../reference/apis/js-apis-promptAction.md#promptactionshowdialog)或者自定义弹窗实现。这样可以让应用界面与系统默认询问框有所区别,提高应用的用户体验度。本文以弹窗为例,介绍如何实现自定义询问框。
284
285在使用页面路由Router相关功能之前,需要在代码中先导入Router模块。
286
287
288```ts
289import router from '@ohos.router';
290```
291
292在事件回调中,调用弹窗的[promptAction.showDialog()](../reference/apis/js-apis-promptAction.md#promptactionshowdialog)方法:
293
294
295```ts
296function onBackClick() {
297  // 弹出自定义的询问框
298  promptAction.showDialog({
299    message: '您还没有完成支付,确定要返回吗?',
300    buttons: [
301      {
302        text: '取消',
303        color: '#FF0000'
304      },
305      {
306        text: '确认',
307        color: '#0099FF'
308      }
309    ]
310  }).then((result) => {
311    if (result.index === 0) {
312      // 用户点击了“取消”按钮
313      console.info('User canceled the operation.');
314    } else if (result.index === 1) {
315      // 用户点击了“确认”按钮
316      console.info('User confirmed the operation.');
317      // 调用router.back()方法,返回上一个页面
318      router.back();
319    }
320  }).catch((err) => {
321    console.error(`Invoke showDialog failed, code is ${err.code}, message is ${err.message}`);
322  })
323}
324```
325
326当用户点击“返回”按钮时,会弹出自定义的询问框,询问用户是否确认返回。选择“取消”将停留在当前页目标页面;选择“确认”将触发router.back()方法,并根据参数决定如何执行跳转。
327