頁(yè)面路由(router)

2024-01-25 13:18 更新

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

頁(yè)面跳轉(zhuǎn)

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

圖1 頁(yè)面跳轉(zhuǎn)

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

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

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

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

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

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

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

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

    1. // 在Home頁(yè)面中
    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. }
    說(shuō)明

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

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

    1. // 在Login頁(yè)面中
    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. }
    說(shuō)明

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

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

    1. // 在Setting頁(yè)面中
    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. }
  • 場(chǎng)景四:有一個(gè)搜索結(jié)果列表頁(yè)(SearchResult)和一個(gè)搜索結(jié)果詳情頁(yè)(SearchDetail),希望從搜索結(jié)果列表頁(yè)點(diǎn)擊某一項(xiàng)結(jié)果,跳轉(zhuǎn)到搜索結(jié)果詳情頁(yè)。同時(shí),如果該結(jié)果已經(jīng)被查看過(guò),則不需要再新建一個(gè)詳情頁(yè),而是直接跳轉(zhuǎn)到已經(jīng)存在的詳情頁(yè)。這種場(chǎng)景下,可以使用replaceUrl()方法,并且使用Single實(shí)例模式。

    1. // 在SearchResult頁(yè)面中
    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ù)傳遞的場(chǎng)景。

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

  1. class DataModelInfo {
  2. age: number;
  3. }
  4. class DataModel {
  5. id: number;
  6. info: DataModelInfo;
  7. }
  8. function onJumpClick(): void {
  9. // 在Home頁(yè)面中
  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)頁(yè)中,可以通過(guò)調(diào)用Router模塊的getParams()方法來(lái)獲取傳遞過(guò)來(lái)的參數(shù)。例如:

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

頁(yè)面返回

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

圖2 頁(yè)面返回

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

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

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

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

    1. router.back();

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

  • 方式二:返回到指定頁(yè)面。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. // 定義一個(gè)返回按鈕的點(diǎn)擊事件處理函數(shù)
  2. function onBackClick(): void {
  3. // 調(diào)用router.showAlertBeforeBackPage()方法,設(shè)置返回詢問(wèn)框的信息
  4. try {
  5. router.showAlertBeforeBackPage({
  6. message: '您還沒(méi)有完成支付,確定要返回嗎?' // 設(shè)置詢問(wèn)框的內(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è)頁(yè)面
  12. router.back();
  13. }

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

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

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

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

自定義詢問(wèn)框

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

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

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

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

  1. function onBackClick() {
  2. // 彈出自定義的詢問(wèn)框
  3. promptAction.showDialog({
  4. message: '您還沒(méi)有完成支付,確定要返回嗎?',
  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è)頁(yè)面
  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í),會(huì)彈出自定義的詢問(wèn)框,詢問(wèn)用戶是否確認(rèn)返回。選擇“取消”將停留在當(dāng)前頁(yè)目標(biāo)頁(yè);選擇“確認(rèn)”將觸發(fā)router.back()方法,并根據(jù)參數(shù)決定如何執(zhí)行跳轉(zhuǎn)。

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)