頁面路由(router)

2024-01-25 13:18 更新

頁面路由指在應(yīng)用程序中實(shí)現(xiàn)不同頁面之間的跳轉(zhuǎn)和數(shù)據(jù)傳遞。HarmonyOS提供了Router模塊,通過不同的url地址,可以方便地進(jìn)行頁面路由,輕松地訪問不同的頁面。本文將從頁面跳轉(zhuǎn)、頁面返回頁面返回前增加一個(gè)詢問框幾個(gè)方面介紹Router模塊提供的功能。

頁面跳轉(zhuǎn)

頁面跳轉(zhuǎn)是開發(fā)過程中的一個(gè)重要組成部分。在使用應(yīng)用程序時(shí),通常需要在不同的頁面之間跳轉(zhuǎn),有時(shí)還需要將數(shù)據(jù)從一個(gè)頁面?zhèn)鬟f到另一個(gè)頁面。

圖1 頁面跳轉(zhuǎn)

Router模塊提供了兩種跳轉(zhuǎn)模式,分別是router.pushUrl()router.replaceUrl()。這兩種模式?jīng)Q定了目標(biāo)頁是否會替換當(dāng)前頁。

  • router.pushUrl():目標(biāo)頁不會替換當(dāng)前頁,而是壓入頁面棧。這樣可以保留當(dāng)前頁的狀態(tài),并且可以通過返回鍵或者調(diào)用router.back()方法返回到當(dāng)前頁。
  • router.replaceUrl():目標(biāo)頁會替換當(dāng)前頁,并銷毀當(dāng)前頁。這樣可以釋放當(dāng)前頁的資源,并且無法返回到當(dāng)前頁。
說明

頁面棧的最大容量為32個(gè)頁面。如果超過這個(gè)限制,可以調(diào)用router.clear()方法清空歷史頁面棧,釋放內(nèi)存空間。

同時(shí),Router模塊提供了兩種實(shí)例模式,分別是Standard和Single。這兩種模式?jīng)Q定了目標(biāo)url是否會對應(yīng)多個(gè)實(shí)例。

  • Standard:標(biāo)準(zhǔn)實(shí)例模式,也是默認(rèn)情況下的實(shí)例模式。每次調(diào)用該方法都會新建一個(gè)目標(biāo)頁,并壓入棧頂。

  • Single:單實(shí)例模式。即如果目標(biāo)頁的url在頁面棧中已經(jīng)存在同url頁面,則離棧頂最近的同url頁面會被移動到棧頂,并重新加載;如果目標(biāo)頁的url在頁面棧中不存在同url頁面,則按照標(biāo)準(zhǔn)模式跳轉(zhuǎn)。

在使用頁面路由Router相關(guān)功能之前,需要在代碼中先導(dǎo)入Router模塊。

  1. import router from '@ohos.router';
  • 場景一:有一個(gè)主頁(Home)和一個(gè)詳情頁(Detail),希望從主頁點(diǎn)擊一個(gè)商品,跳轉(zhuǎn)到詳情頁。同時(shí),需要保留主頁在頁面棧中,以便返回時(shí)恢復(fù)狀態(tài)。這種場景下,可以使用pushUrl()方法,并且使用Standard實(shí)例模式(或者省略)。

    1. // 在Home頁面中
    2. function onJumpClick(): void {
    3. router.pushUrl({
    4. url: 'pages/Detail' // 目標(biāo)url
    5. }, router.RouterMode.Standard, (err) => {
    6. if (err) {
    7. console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
    8. return;
    9. }
    10. console.info('Invoke pushUrl succeeded.');
    11. });
    12. }
    說明

    標(biāo)準(zhǔn)實(shí)例模式下,router.RouterMode.Standard參數(shù)可以省略。

  • 場景二:有一個(gè)登錄頁(Login)和一個(gè)個(gè)人中心頁(Profile),希望從登錄頁成功登錄后,跳轉(zhuǎn)到個(gè)人中心頁。同時(shí),銷毀登錄頁,在返回時(shí)直接退出應(yīng)用。這種場景下,可以使用replaceUrl()方法,并且使用Standard實(shí)例模式(或者省略)。

    1. // 在Login頁面中
    2. function onJumpClick(): void {
    3. router.replaceUrl({
    4. url: 'pages/Profile' // 目標(biāo)url
    5. }, router.RouterMode.Standard, (err) => {
    6. if (err) {
    7. console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
    8. return;
    9. }
    10. console.info('Invoke replaceUrl succeeded.');
    11. })
    12. }
    說明

    標(biāo)準(zhǔn)實(shí)例模式下,router.RouterMode.Standard參數(shù)可以省略。

  • 場景三:有一個(gè)設(shè)置頁(Setting)和一個(gè)主題切換頁(Theme),希望從設(shè)置頁點(diǎn)擊主題選項(xiàng),跳轉(zhuǎn)到主題切換頁。同時(shí),需要保證每次只有一個(gè)主題切換頁存在于頁面棧中,在返回時(shí)直接回到設(shè)置頁。這種場景下,可以使用pushUrl()方法,并且使用Single實(shí)例模式。

    1. // 在Setting頁面中
    2. function onJumpClick(): void {
    3. router.pushUrl({
    4. url: 'pages/Theme' // 目標(biāo)url
    5. }, router.RouterMode.Single, (err) => {
    6. if (err) {
    7. console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
    8. return;
    9. }
    10. console.info('Invoke pushUrl succeeded.');
    11. });
    12. }
  • 場景四:有一個(gè)搜索結(jié)果列表頁(SearchResult)和一個(gè)搜索結(jié)果詳情頁(SearchDetail),希望從搜索結(jié)果列表頁點(diǎn)擊某一項(xiàng)結(jié)果,跳轉(zhuǎn)到搜索結(jié)果詳情頁。同時(shí),如果該結(jié)果已經(jīng)被查看過,則不需要再新建一個(gè)詳情頁,而是直接跳轉(zhuǎn)到已經(jīng)存在的詳情頁。這種場景下,可以使用replaceUrl()方法,并且使用Single實(shí)例模式。

    1. // 在SearchResult頁面中
    2. function onJumpClick(): void {
    3. router.replaceUrl({
    4. url: 'pages/SearchDetail' // 目標(biāo)url
    5. }, router.RouterMode.Single, (err) => {
    6. if (err) {
    7. console.error(`Invoke replaceUrl failed, code is ${err.code}, message is ${err.message}`);
    8. return;
    9. }
    10. console.info('Invoke replaceUrl succeeded.');})
    11. }

以上是不帶參數(shù)傳遞的場景。

如果需要在跳轉(zhuǎn)時(shí)傳遞一些數(shù)據(jù)給目標(biāo)頁,則可以在調(diào)用Router模塊的方法時(shí),添加一個(gè)params屬性,并指定一個(gè)對象作為參數(shù)。例如:

  1. class DataModelInfo {
  2. age: number;
  3. }
  4. class DataModel {
  5. id: number;
  6. info: DataModelInfo;
  7. }
  8. function onJumpClick(): void {
  9. // 在Home頁面中
  10. let paramsInfo: DataModel = {
  11. id: 123,
  12. info: {
  13. age: 20
  14. }
  15. };
  16. router.pushUrl({
  17. url: 'pages/Detail', // 目標(biāo)url
  18. params: paramsInfo // 添加params屬性,傳遞自定義參數(shù)
  19. }, (err) => {
  20. if (err) {
  21. console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
  22. return;
  23. }
  24. console.info('Invoke pushUrl succeeded.');
  25. })
  26. }

在目標(biāo)頁中,可以通過調(diào)用Router模塊的getParams()方法來獲取傳遞過來的參數(shù)。例如:

  1. const params = router.getParams(); // 獲取傳遞過來的參數(shù)對象
  2. const id = params['id']; // 獲取id屬性的值
  3. const age = params['info'].age; // 獲取age屬性的值

頁面返回

當(dāng)用戶在一個(gè)頁面完成操作后,通常需要返回到上一個(gè)頁面或者指定頁面,這就需要用到頁面返回功能。在返回的過程中,可能需要將數(shù)據(jù)傳遞給目標(biāo)頁,這就需要用到數(shù)據(jù)傳遞功能。

圖2 頁面返回

在使用頁面路由Router相關(guān)功能之前,需要在代碼中先導(dǎo)入Router模塊。

  1. import router from '@ohos.router';

可以使用以下幾種方式進(jìn)行頁面返回:

  • 方式一:返回到上一個(gè)頁面。

    1. router.back();

    這種方式會返回到上一個(gè)頁面,即上一個(gè)頁面在頁面棧中的位置。但是,上一個(gè)頁面必須存在于頁面棧中才能夠返回,否則該方法將無效。

  • 方式二:返回到指定頁面。

    1. router.back({
    2. url: 'pages/Home'
    3. });

    這種方式可以返回到指定頁面,需要指定目標(biāo)頁的路徑。目標(biāo)頁必須存在于頁面棧中才能夠返回。

  • 方式三:返回到指定頁面,并傳遞自定義參數(shù)信息。

    1. router.back({
    2. url: 'pages/Home',
    3. params: {
    4. info: '來自Home頁'
    5. }
    6. });

    這種方式不僅可以返回到指定頁面,還可以在返回的同時(shí)傳遞自定義參數(shù)信息。這些參數(shù)信息可以在目標(biāo)頁中通過調(diào)用router.getParams()方法進(jìn)行獲取和解析。

在目標(biāo)頁中,在需要獲取參數(shù)的位置調(diào)用router.getParams()方法即可,例如在onPageShow()生命周期回調(diào)中:

  1. onPageShow() {
  2. const params = router.getParams(); // 獲取傳遞過來的參數(shù)對象
  3. const info = params['info']; // 獲取info屬性的值
  4. }
說明

當(dāng)使用router.back()方法返回到指定頁面時(shí),原棧頂頁面(包括)到指定頁面(不包括)之間的所有頁面棧都將從棧中彈出并銷毀。

另外,如果使用router.back()方法返回到原來的頁面,原頁面不會被重復(fù)創(chuàng)建,因此使用@State聲明的變量不會重復(fù)聲明,也不會觸發(fā)頁面的aboutToAppear()生命周期回調(diào)。如果需要在原頁面中使用返回頁面?zhèn)鬟f的自定義參數(shù),可以在需要的位置進(jìn)行參數(shù)解析。例如,在onPageShow()生命周期回調(diào)中進(jìn)行參數(shù)解析。

頁面返回前增加一個(gè)詢問框

在開發(fā)應(yīng)用時(shí),為了避免用戶誤操作或者丟失數(shù)據(jù),有時(shí)候需要在用戶從一個(gè)頁面返回到另一個(gè)頁面之前,彈出一個(gè)詢問框,讓用戶確認(rèn)是否要執(zhí)行這個(gè)操作。

本文將從系統(tǒng)默認(rèn)詢問框自定義詢問框兩個(gè)方面來介紹如何實(shí)現(xiàn)頁面返回前增加一個(gè)詢問框的功能。

圖3 頁面返回前增加一個(gè)詢問框

系統(tǒng)默認(rèn)詢問框

為了實(shí)現(xiàn)這個(gè)功能,可以使用頁面路由Router模塊提供的兩個(gè)方法:router.showAlertBeforeBackPage()router.back()來實(shí)現(xiàn)這個(gè)功能。

在使用頁面路由Router相關(guān)功能之前,需要在代碼中先導(dǎo)入Router模塊。

  1. import router from '@ohos.router';

如果想要在目標(biāo)界面開啟頁面返回詢問框,需要在調(diào)用router.back()方法之前,通過調(diào)用router.showAlertBeforeBackPage()方法設(shè)置返回詢問框的信息。例如,在支付頁面中定義一個(gè)返回按鈕的點(diǎn)擊事件處理函數(shù):

  1. // 定義一個(gè)返回按鈕的點(diǎn)擊事件處理函數(shù)
  2. function onBackClick(): void {
  3. // 調(diào)用router.showAlertBeforeBackPage()方法,設(shè)置返回詢問框的信息
  4. try {
  5. router.showAlertBeforeBackPage({
  6. message: '您還沒有完成支付,確定要返回嗎?' // 設(shè)置詢問框的內(nèi)容
  7. });
  8. } catch (err) {
  9. console.error(`Invoke showAlertBeforeBackPage failed, code is ${err.code}, message is ${err.message}`);
  10. }
  11. // 調(diào)用router.back()方法,返回上一個(gè)頁面
  12. router.back();
  13. }

其中,router.showAlertBeforeBackPage()方法接收一個(gè)對象作為參數(shù),該對象包含以下屬性:

  • message:string類型,表示詢問框的內(nèi)容。

    如果調(diào)用成功,則會在目標(biāo)界面開啟頁面返回詢問框;如果調(diào)用失敗,則會拋出異常,并通過err.code和err.message獲取錯(cuò)誤碼和錯(cuò)誤信息。

    當(dāng)用戶點(diǎn)擊“返回”按鈕時(shí),會彈出確認(rèn)對話框,詢問用戶是否確認(rèn)返回。選擇“取消”將停留在當(dāng)前頁目標(biāo)頁;選擇“確認(rèn)”將觸發(fā)router.back()方法,并根據(jù)參數(shù)決定如何執(zhí)行跳轉(zhuǎn)。

自定義詢問框

自定義詢問框的方式,可以使用彈窗或者自定義彈窗實(shí)現(xiàn)。這樣可以讓應(yīng)用界面與系統(tǒng)默認(rèn)詢問框有所區(qū)別,提高應(yīng)用的用戶體驗(yàn)度。本文以彈窗為例,介紹如何實(shí)現(xiàn)自定義詢問框。

在使用頁面路由Router相關(guān)功能之前,需要在代碼中先導(dǎo)入Router模塊。

  1. import router from '@ohos.router';

在事件回調(diào)中,調(diào)用彈窗的promptAction.showDialog()方法:

  1. function onBackClick() {
  2. // 彈出自定義的詢問框
  3. promptAction.showDialog({
  4. message: '您還沒有完成支付,確定要返回嗎?',
  5. buttons: [
  6. {
  7. text: '取消',
  8. color: '#FF0000'
  9. },
  10. {
  11. text: '確認(rèn)',
  12. color: '#0099FF'
  13. }
  14. ]
  15. }).then((result) => {
  16. if (result.index === 0) {
  17. // 用戶點(diǎn)擊了“取消”按鈕
  18. console.info('User canceled the operation.');
  19. } else if (result.index === 1) {
  20. // 用戶點(diǎn)擊了“確認(rèn)”按鈕
  21. console.info('User confirmed the operation.');
  22. // 調(diào)用router.back()方法,返回上一個(gè)頁面
  23. router.back();
  24. }
  25. }).catch((err) => {
  26. console.error(`Invoke showDialog failed, code is ${err.code}, message is ${err.message}`);
  27. })
  28. }

當(dāng)用戶點(diǎn)擊“返回”按鈕時(shí),會彈出自定義的詢問框,詢問用戶是否確認(rèn)返回。選擇“取消”將停留在當(dāng)前頁目標(biāo)頁;選擇“確認(rèn)”將觸發(fā)router.back()方法,并根據(jù)參數(shù)決定如何執(zhí)行跳轉(zhuǎn)。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號