目录

Page Routing (@ohos.router) (Not Recommended)

Page routing refers to the redirection and data transfer between different pages in an application. It can be implemented through APIs of the Router module. Through different URLs, you can easily navigate users through pages. This document outlines the key features of the Router module, including: Page Redirection, Page Return, Adding a Confirmation Dialog Box Before Page Return, and Named Route.

You are advised to use Component Navigation (Navigation), which offers enhanced functionality and customization capabilities, as the routing framework in your application. For details about the differences between Navigation and Router, see Transition from Router to Navigation.

Page Redirection

Page redirection is an important part of the development process. When using an application, you usually need to jump between different pages, and sometimes you need to pass data from one page to another.

Figure 1 Page redirection

The Router module provides two redirection modes: pushUrl and replaceUrl. Whether the target page will replace the current page depends on the mode used.

  • When creating a page, configure the route to this page by following instructions in Building the Second Page.

  • The maximum capacity of a page stack is 32 pages. If this limit is exceeded, the clear API can be called to clear the historical page stack and free the memory.

The Router module also provides two instance modes: Standard and Single. Depending on the mode, the target URL is mapped to one or more instances.

The preceding scenarios do not involve parameter transfer.

If you need to transfer data to the target page during redirection, you can add a params attribute and specify an object as a parameter when invoking an API of the Router module. Example:

class DataModelInfo {
  public age: number = 0;
}

class DataModel {
  public id: number = 0;
  public info: DataModelInfo | null = null;
}
onJumpClick(): void {
  // On the Home page
  let paramsInfo: DataModel = {
    id: 123,
    info: {
      age: 20
    }
  };

  this.getUIContext().getRouter().pushUrl({
    url: 'pages/pageRouter/jumpPage/DetailPara', // Target URL.
    params: paramsInfo // Add the params attribute to transfer custom parameters.
  }, (err) => {
    if (err) {
      hilog.error(DOMAIN, TAG,`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);
      return;
    }
    hilog.info(DOMAIN, TAG,'Invoke pushUrl succeeded.');
  });
}

On the target page, you can call the getParams API of the Router module to obtain the passed parameters. Example:

class InfoTmp {
  public age: number = 0;
}

class RouTmp {
  // id: object = () => {
  // };
  public id: number = 0;
  public info: InfoTmp = new InfoTmp();
}
private params: RouTmp = (this.getUIContext().getRouter().getParams()) as RouTmp; // Obtain the passed parameter object.
// private id: number = this.params.id; // Obtain the value of the id attribute.
private age: number = this.params.info.age; // Obtain the value of the age attribute.

Page Return

Implement the page return feature so that users can return to the previous page or a specified page. You can pass parameters to the target page during the return process.

Figure 2 Page return

Directly using router can lead to the issue of ambiguous UI context. To avoid this, obtain a UIContext instance using the getUIContext() API, and then obtain the router object bound to that instance through the getRouter API.

You can use any of the following methods to return to a page:

this.getUIContext().getRouter().back();

This method allows you to return to the position of the previous page in the page stack. For this method to work, the previous page must exist in the page stack.

On the target page, call getParams where the parameters are needed, for example, in the onPageShow lifecycle callback.

Directly using router can lead to the issue of ambiguous UI context. To avoid this, obtain a UIContext instance using the getUIContext() API, and then obtain the router object bound to that instance through the getRouter API.

@Entry
@Component
struct Home {
  @State message: string = 'Hello World';

  onPageShow() {
    const params = this.getUIContext().getRouter().getParams() as Record<string, string>; // Obtain the passed parameter object.
    if (params) {
      const info: string = params.info as string; // Obtain the value of the info attribute.
    }
  }

// ···
}

When the back API is used to return to a specified page, all pages between the top page (included) and the specified page (excluded) are pushed from the page stack and destroyed.

Additionally, if you use the back method to return to the previous page, the original page will not be recreated. Therefore, variables declared with @State will not be redeclared, and the aboutToAppear lifecycle callback will not be triggered. If you want to use the custom parameters transferred from the returned page on the original page, you can parse the parameters in the required position. For example, parameter parsing can be performed in the onPageShow lifecycle callback.

Lifecycle

The router refers to a lifecycle function of components decorated with @Entry and provides the following lifecycle callbacks. For details about the lifecycle sequence diagram of onPageShow and onPageHide, see Lifecycle.

import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0xF811;
const TAG = '[Sample_ArkTSRouter]';
// Index.ets
@Entry
@Component
struct MyComponent {
  // Only components decorated with @Entry can call the lifecycle callbacks of a page.
  onPageShow() {
    hilog.info(DOMAIN, TAG, 'Index onPageShow');
  }

  // Only components decorated with @Entry can call the lifecycle callbacks of a page.
  onPageHide() {
    hilog.info(DOMAIN, TAG, 'Index onPageHide');
  }

  // Only components decorated with @Entry can call the lifecycle callbacks of a page.
  onBackPress() {
    hilog.info(DOMAIN, TAG, 'Index onBackPress');
    // The value true means that the page executes its own return logic, and false (default) means that the default return logic is used.
    return true;
  }

  build() {
    Column() {
      // Push to Page and execute onPageHide.
      Button('push to next page')
        .onClick(() => {
          this.getUIContext().getRouter().pushUrl({ url: 'pages/pageRouter/lifeCycle/Page' });
        })
    }
  }
}
 import { hilog } from '@kit.PerformanceAnalysisKit';
 const DOMAIN = 0xF811;
 const TAG = '[Sample_ArkTSRouter]';
// Page.ets
@Entry
@Component
struct Page {
  @State textColor: Color = Color.Black;
  @State num: number = 0;

  // Only components decorated with @Entry can call the lifecycle callbacks of a page.
  onPageShow() {
    hilog.info(DOMAIN, TAG, 'Page onPageShow');
    this.num = 5;
  }

  // Only components decorated with @Entry can call the lifecycle callbacks of a page.
  onPageHide() {
    hilog.info(DOMAIN, TAG, 'Page onPageHide');
  }

  // Only components decorated with @Entry can call the lifecycle callbacks of a page.
  onBackPress() { // If the value is not set, false is used.
    hilog.info(DOMAIN, TAG, 'Page onBackPress');
    this.textColor = Color.Grey;
    this.num = 0;
  }

  build() {
    Column() {
      Text(`num: ${this.num}`)
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.textColor)
        .margin(20)
        .onClick(() => {
          this.num += 5;
        })
      Button('pop to previous page')
        .onClick(() => {
          this.getUIContext().getRouter().back();
        })
    }
    .width('100%')
  }
}

Defining a Custom Transition

pageTransition can be used to customize router page transitions. For details, see Page Transition (pageTransition).

Adding a Confirmation Dialog Box Before Page Return

During application development, to prevent misoperations or data loss, a dialog box needs to be displayed before a user returns from one page to another, asking the user whether to perform the operation.

Such a dialog box can be in the default style or custom style.

Figure 3 Adding a confirmation dialog box before page return

[h2]Default Confirmation Dialog Box

To implement this feature, you can use the showAlertBeforeBackPage and back APIs provided by the Router module.

Directly using router can lead to the issue of ambiguous UI context. To avoid this, obtain a UIContext instance using the getUIContext() API, and then obtain the router object bound to that instance through the getRouter API.

To enable the confirmation dialog box for page return, call the showAlertBeforeBackPage API (for setting the information about the dialog box), then the back API. For example, define a click event processing function for the back button on the payment page:

import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0xF811;
const TAG = '[Sample_ArkTSRouter]';
// Define a click event processing function for the back button.
onBackClick(): void {
  // Call this.getUIContext().getRouter().showAlertBeforeBackPage to set the information about the confirmation dialog box.
  try {
    this.getUIContext().getRouter().showAlertBeforeBackPage({
      // Configure the resource whose name is 'pageRouter_dialog_context' and value is a non-empty string in the resources\base\element\string.json file.
      message: this.getUIContext().getHostContext()?.resourceManager.getStringByNameSync('pageRouter_dialog_context') as string, // Set the content of the confirmation dialog box.
    });
  } catch (err) {
    let message = (err as BusinessError).message;
    let code = (err as BusinessError).code;
    hilog.error(DOMAIN, TAG,`Invoke showAlertBeforeBackPage failed, code is ${code}, message is ${message}`);
  }

  // Call this.getUIContext().getRouter().back() to return to the previous page.
  this.getUIContext().getRouter().back();
}

The this.getUIContext().getRouter().showAlertBeforeBackPage API receives an object as a parameter. The object contains the following attributes:

message: content of the dialog box. The value is of the string type.

If the API is called successfully, the confirmation dialog box is displayed on the target page. Otherwise, an exception is thrown and the error code and error information is obtained through err.code and err.message.

When the user clicks the back button, a confirmation dialog box is displayed, prompting the user to confirm their operation. If the user selects Cancel, the application stays on the current page. If the user selects OK, the back API is called and the redirection is performed based on the parameters.

[h2]Custom Confirmation Dialog Box

To implement a custom confirmation dialog box, use showDialog or create a custom dialog box . This topic uses the APIs in the PromptAction module an example to describe how to implement a custom confirmation dialog box.

Directly using router can lead to the issue of ambiguous UI context. To avoid this, obtain a UIContext instance using the getUIContext() API, and then obtain the router object bound to that instance through the getRouter API.

In the event callback, call the showDialog API.

import { promptAction } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0xF811;
const TAG = '[Sample_ArkTSRouter]';
onBackClick() {
  // Display a custom confirmation dialog box.
  this.getUIContext().getPromptAction().showDialog({
    // "You have not completed payment yet. Are you sure you want to go back?"
    // Replace $r('app.string.pageRouter_dialog_context') with the actual resource file. In this example, the value in the resource file is "You have not completed payment yet. Are you sure you want to go back?"
    message: $r('app.string.pageRouter_dialog_context'),
    buttons: [
      {
        // Replace $r('app.string.pageRouter_dialog_canceled') with the actual resource file. In this example, the value in the resource file is "Cancel."
        text: $r('app.string.pageRouter_dialog_canceled'),
        color: '#FF0000'
      },
      {
        // Replace $r('app.string.pageRouter_dialog_confirmed') with the actual resource file. In this example, the value in the resource file is "OK."
        text: $r('app.string.pageRouter_dialog_confirmed'),
        color: '#0099FF'
      }
    ]
  }).then((result: promptAction.ShowDialogSuccessResponse) => {
    if (result.index === 0) {
      // The user selects Cancel.
      hilog.info(DOMAIN, TAG, 'User canceled the operation.');
    } else if (result.index === 1) {
      // The user selects OK.
      hilog.info(DOMAIN, TAG, 'User confirmed the operation.');
      // Call this.getUIContext().getRouter().back() to return to the previous page.
      this.getUIContext().getRouter().back();
    }
  }).catch((err: Error) => {
    let message = (err as BusinessError).message;
    let code = (err as BusinessError).code;
    hilog.error(DOMAIN, TAG, `Invoke showDialog failed, code is ${code}, message is ${message}`);
  });
}

When the user clicks the back button, the custom confirmation dialog box is displayed, prompting the user to confirm their operation. If the user selects Cancel, the application stays on the current page. If the user selects OK, the back API is called and the redirection is performed based on the parameters.

Named Route

To redirect to a page in a HAR or HSP, you can use pushNamedRoute.

Figure 4 Named route redirection

In the HAR or HSP page that you want to navigate to, name the EntryOptions of the custom component decorated by @Entry:

// library/src/main/ets/pages/Index.ets
// library is the custom name of the new shared package.
@Entry({ routeName: 'myPage' })
@Component
export struct MyComponent {
  build() {
    Row() {
      Column() {
        Text('Library Page')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }
}

When the configuration is successful, import the named route page to the page from which you want to redirect.

To use the named route for redirection, you must configure dependencies in the oh-package.json5 file of the application package. Example:

"dependencies": {
   "library": "file:../library",
   // ...
}
import { BusinessError } from '@kit.BasicServicesKit';
import 'library/src/main/ets/pages/Index'; // Import the named route page from the library of the shared package.
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0xF811;
const TAG = '[Sample_ArkTSRouter]';

@Entry
@Component
struct Index {
  build() {
    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
      Text('Hello World')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20 })
        .backgroundColor('#ccc')
        .onClick(() => { // Click to go to a page in another shared package.
          try {
            this.getUIContext().getRouter().pushNamedRoute({
              name: 'myPage',
              params: {
                data1: 'message',
                data2: {
                  data3: [123, 456, 789]
                }
              }
            });
          } catch (err) {
            let message = (err as BusinessError).message;
            let code = (err as BusinessError).code;
            hilog.error(DOMAIN, TAG,`pushNamedRoute failed, code is ${code}, message is ${message}`);
          }
        })
    }
    .width('100%')
    .height('100%')
  }
}