This content originally appeared on DEV Community and was authored by 程序员一鸣
Foreword
this article is based on Api12
if you are still using router as a page jump, it is recommended to switch the Navigation component as the application routing framework, not for anything else, because the official router is no longer recommend.
It should be noted that Navigation is a component, not a callable method like router, it is generally used as the root container of the home page.
Simple to use
simple implementation of A small case, jump from page A to page B. According to the official case, roughly three steps can be.
In the first step, replace the main portal page with Navigation and set NavPathStack, because NavPathStack is used to execute the jump logic.
@Entry
@Component
struct Index {
pageStack: NavPathStack = new NavPathStack()
build() {
Navigation(this.pageStack) {
RelativeContainer() {
Button("click")
.onClick(() => {
this.pageStack.pushPath({ name: "TestPage" })
})
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.height('100%')
.width('100%')
}
}
}
In the second step, the jump target page uses NavDestination as the root layout and declares a jump page entry function.
@Builder
export function TestPageBuilder() {
TestPage()
}
@Component
struct TestPage {
@State message: string = 'Hello TestPage';
build() {
NavDestination() {
RelativeContainer() {
Text(this.message)
.id('TestPageHelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.height('100%')
.width('100%')
}
}
}
The third step is to add the routing table configuration. The configuration file module.json5 of the jump target module is added:
{
"module" : {
"routerMap": "$profile:route_map"
}
}
the route_map.json file is configured as follows:
{
"routerMap": [
{
"name": "TestPage",
"pageSourceFile": "src/main/ets/pages/TestPage.ets",
"buildFunction": "TestPageBuilder"
}
]
}
after the above three steps are completed, we simply realize the page jump, of course, as a routing container, Navigation has its own life cycle and many available properties or methods. Let's take a common example.
Example A simple outline to facilitate our intuitive understanding:
1. Understand the life cycle of Navigation.
2, Navigation common property methods.
3, NavPathStack common attribute methods.
4. How to use code to dynamically configure routing tables.
5, common methods of use.
First, understand the life cycle of Navigation.
You can verify a problem. When the Navigation component is used, there will be a common problem, that is, the onPageShow and onPageHide declaration cycle of subpages will not go.
aboutToAppear(): void {
console.log("===:aboutToAppear")
}
onPageShow(): void {
console.log("===:onPageShow")
}
onPageHide(): void {
console.log("===:onPageHide")
}
When jumping to the target page, the console only prints the aboutToAppear:
the main reason is that, as a routing container, the Navigation lifecycle is hosted on the NavDestination component and opened in the form of component events.
How to know the display or hiding of the page, or switch the foreground and background, need to pass the life cycle method of NavDestination is obtained:
OnWillShow: The NavDestination component is executed before the layout is displayed, and the page is not visible at this time (switching the application to the foreground will not trigger it).
OnShown: Execute after the layout of the NavDestination component is displayed, and the page layout is now complete.
OnWillHide: Execute before the NavDestination component triggers hiding (application switching to the background will not trigger it).
OnHidden: Execute after the NavDestination component triggers hiding (push the non stack top page to the stack, pop the stack top page to the stack, or switch the application to the background)
II. Navigation Common Attribute Methods
it should be noted that although Navigation provides many methods, in actual development, only a handful of them are used, because in general, we don't need any Navigation bar or title bar. After all, the system does not conform to our UI design and only needs to be hidden.
For example, the title bar provided is shown below, which can match the actual UI, which can be said to be very low. Of course, if your design is similar, you can use the system completely.
1, title, set the page title
that is, the main title in the above figure is directly set as follows:
.title("title")
due subTitle the subtitle is obsolete, and the official alternative is to use title instead:
.title(this.NavigationTitle)
customize the layout via @ Builder.
@Builder NavigationTitle() {
Column() {
Text('Title')
.fontColor('#182431')
.fontSize(30)
.lineHeight(41)
.fontWeight(700)
Text('subtitle')
.fontColor('#182431')
.fontSize(14)
.lineHeight(19)
.opacity(0.4)
.margin({ top: 2, bottom: 20 })
}.alignItems(HorizontalAlign.Start)
}
Effect:
2, menus , settings page upper right corner menu
.menus(this.NavigationMenus)
customize the layout via @ Builder.
@Builder
NavigationMenus() {
Row() {
Image($r("app.media.app_icon"))
.width(24)
.height(24)
Image($r("app.media.app_icon"))
.width(24)
.height(24)
.margin({ left: 24 })
}
}
Effect:
3, titleMode , set Page Title Bar Display Mode
currently, there are three official models, full: fixed to large title mode, Mini : fixed to subtitle mode, free: When the content is a scrollable component with a full screen, the title shrinks as the content scrolls up (the size of the subtitle does not change and fades out). Scroll the content down to the top and return to the original.
4, backButtonIcon , set the return key icon in the title bar
.backButtonIcon(new SymbolGlyphModifier($r('app.media.app_icon')))
5, mode , display mode of the navigation bar
set the display mode of the navigation bar. Supports Stack, Split, and Auto modes.
Of course, there are many attributes. If you use the title bar provided by the system, try to get familiar with the government. In actual development, these are actually unnecessary and can be hidden directly.
When we do not set anything, we will find that the content area cannot be covered completely. This is due to the title bar. We only need to hide it.
Before not hidden:
after hiding:
.hideTitleBar(true)
of course, NavDestination also has the hideTitleBar attribute. If you use your own UI title bar, you also need to set it to true.
III. Common Attribute Methods of NavPathStack
NavPathStack is the Navigation routing stack is used to manage routes, such as jump, removal, etc. It is very important. For several common attributes, let's briefly talk about them.
- pushPath
the page redirects the information of the NavDestination page specified by info to the stack.
this.pageStack.pushPath({ name: "TestPage" })
Two parameters, one is NavPathInfo and the other is NavigationOptions. This is the version of api12 +. If it is the following version, the second parameter is boolean type, which means whether to support transition animation.
NavPathInfo object, name refers to the name of the NavDestination page, param is the parameter passed, and onPop is the callback returned when the NavDestination page triggers pop.
Such as passing parameters
this.pageStack.pushPath({ name: "TestPage",param:"params"})
the second parameter, NavigationOptions, can be set the operation mode and Transition animation of the page stack, such as setting find from the bottom of the stack to the top of the stack support Transition animation:
this.pageStack.pushPath({ name: "TestPage",param:"params"},{
launchMode:LaunchMode.POP_TO_SINGLETON,
animated:true
})
2, pushPathByName
the NavDestination page information specified by name is added to the stack.
this.pageStack.pushPathByName("TestPage","params")
Three parameters, the first refers to the NavDestination page name, the second is the passed parameter, and the last is boolean type, whether to support transition animation.
3, pushDestination
and consistent pushPath, add the information of the NavDestination page specified by info to the stack, and use the Promise asynchronous callback to return the interface call result.
- pushDestinationByName
and pushPathByName is consistent,Add the NavDestination page information specified by name to the stack, and use the Promise asynchronous callback to return the interface call result.
- replacePath
the parameter is the same as that of pushPath, which is mainly used to replace page stack operations.
- Replace pathbyname
and the parameters of pushPathByName are the same, exit the top of the current page stack and push the page specified by name into the stack.
this.pageStack.replacePathByName("TestPage","params",true)
7, pop.
The top element of the routing stack pops up, that is, the current page is destroyed, and the onPop callback is triggered to pass in the page processing result.
this.pageStack.pop("result")
8, popToName
roll back the routing stack to the first NavDestination page named name from the bottom of the stack. , and pop , used in the same way, but the first parameter is. The NavDestination page name.
9, popToIndex
roll back the routing stack to the NavDestination page specified by index , and pop , used in the same way, but the first parameter is. The index of the page stack.
10, moveToTop
Move the first NavDestination page named name from the bottom of the stack to the top of the stack.
11, moveIndexToTop
moves the NavDestination page specified by index to the top of the stack.
12, clear
clears all pages in the stack.
Fourth, how to use code to dynamically configure the routing table.
At the beginning, we used the statically configured route to realize the jump. Each page needs to be configured in the route json file, which is very inconvenient. For this problem, the government also provided us customize the routing table to achieve cross-packet dynamic routing.
According to the official interpretation, the specific implementation plan is as follows:
- Define page jump configuration items.
It is defined using a resource file, which is parsed at run time by Resource Management @ ohos.resourceManager.
Configure the routing loading configuration items in the ets file, which generally include the routing page name (that is, the alias of the page in interfaces such as pushPath), the module name where the file is located (the module name of hsp/har), and the path of the loading page in the module (the path relative to the src directory).
Load the target jump page, load the module where the jump target page is located at runtime through dynamic import, call the method in the module after the module is loaded, load the target page displayed in the module through import in the method of the module, and return the Builder function defined after the page is loaded.
Trigger the page jump, and execute the Builder function loaded in step 2 in the navDestination attribute of Navigation to jump to the target page.
We simply implement a small case:
the first step is to create a static routing module. This module is used to store routing-related tool classes, configure routing loading configuration items, and rely on the modules that need to be used, that is, all modules involved in routing jumps need to rely on this module.
Routing tool class:
export class RouterModule {
static builderMap: Map<string, WrappedBuilder<[object]>> = new Map<string, WrappedBuilder<[object]>>();
static routerMap: Map<string, NavPathStack> = new Map<string, NavPathStack>();
// Registering a builder by name.
public static registerBuilder(builderName: string, builder: WrappedBuilder<[object]>): void {
RouterModule.builderMap.set(builderName, builder);
}
// Get builder by name.
public static getBuilder(builderName: string): WrappedBuilder<[object]> {
const builder = RouterModule.builderMap.get(builderName);
return builder as WrappedBuilder<[object]>;
}
// Registering a router by name.
public static createRouter(routerName: string, router: NavPathStack): void {
RouterModule.routerMap.set(routerName, router);
}
// Get router by name.
public static getRouter(routerName: string): NavPathStack {
return RouterModule.routerMap.get(routerName) as NavPathStack;
}
// Jumping to a Specified Page by Obtaining the Page Stack.
public static async push(router: RouterModel): Promise<void> {
const harName = router.builderName.split('_')[0];
await import(harName).then((ns: ESObject): Promise<void> => ns.harInit(router.builderName))
RouterModule.getRouter(router.routerName).pushPath({ name: router.builderName, param: router.param });
}
// Obtain the page stack and pop it.
public static pop(routerName: string): void {
// Find the corresponding route stack for pop.
RouterModule.getRouter(routerName).pop();
}
// Get the page stack and clear it.
public static clear(routerName: string): void {
// Find the corresponding route stack for pop.
RouterModule.getRouter(routerName).clear();
}
// Directly jump to the specified route.
public static popToName(routerName: string, builderName: string): void {
RouterModule.getRouter(routerName).popToName(builderName);
}
}
route static variable
export class BuilderNameConstants {
static readonly Test: string = 'Test';
}
// Indicates the key of the routerMap table in the RouterModule.
export class RouterNameConstants {
static readonly ENTRY_HAP: string = 'EntryHap_Router';
}
routing Model Object
export class RouterModel {
// Route page alias, in the form:${bundleName}_${pageName}.
builderName: string = "";
// Routing Stack Name.
routerName: string = "";
// Parameters that need to be transferred to the page.
param?: object = new Object();
}
the second step, the main page configuration
@Entry
@Component
struct Index {
private pageStack: NavPathStack = new NavPathStack()
aboutToAppear() {
RouterModule.createRouter(RouterNameConstants.ENTRY_HAP, this.pageStack);
}
@Builder
routerMap(builderName: string, param: object) {
RouterModule.getBuilder(builderName).builder(param);
}
build() {
Navigation(this.pageStack) {
RelativeContainer() {
Button("click")
.onClick(() => {
RouterModule.getRouter(RouterNameConstants.ENTRY_HAP)
.pushPath({ name: BuilderNameConstants.Test })
})
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.width('100%')
.height('100%')
.backgroundColor(Color.Pink)
}.width('100%')
.height('100%')
.hideTitleBar(true)
.navDestination(this.routerMap);
}
}
the third step, sub-page configuration
@Component
struct TestPage {
build() {
Column() {
Text("child")
}
.width('100%')
.height('100%')
}
}
@Builder
export function TestBuilder(value: object) {
NavDestination() {
TestPage()
}
.hideTitleBar(true)
}
const builderName = BuilderNameConstants.Test;
if (!RouterModule.getBuilder(builderName)) {
const builder: WrappedBuilder<[object]> = wrapBuilder(TestBuilder);
RouterModule.registerBuilder(builderName, builder);
}
the fourth step, initialization, dynamic package guide, can be initialized in Ability or AbilityStage.
export function importPages() {
import('../pages/TestPage')
}
In the above four steps, we have implemented a dynamic routing configuration, which is also a bit complicated. After all, dynamic package guide needs to be manually configured. In the next article, we will simplify the above program.
V. Summary of Common Use Problems
1. How to get NavPathStack for sub-pages
all actions are executed through the NavPathStack object. On the main page, we declare Navigation and pass NavPathStack. Then the subpage does not have NavPathStack object. How to jump? It is very simple, just need to pass to the subpage.
The @ Provide decorator and @ Consume decorator are used here, that is, bidirectional synchronization with descendant components.
When declared on the Main Page
@Provide('pageStack') pageStack: NavPathStack = new NavPathStack()
subpage Receive
@Consume('pageStack') pageStack: NavPathStack;
2. How does the page get the passed parameters
gets the passed data based on the page Name.
this.pageStack.getParamByName("TestPage")
In addition, according to the index
this.pageStack.getParamByIndex(1)
3. How does the page receive the returned parameters
for example, return, we casually pass a data:
this.pageStack.pop("data")
receive the returned data
this.pageStack.pushPath({
name: "TestPage", onPop: (info) => {
console.log("==========" + info.result)
}
})
4. How to intercept routes
this.pageStack.setInterception({
willShow: (from: NavDestinationContext | "navBar", to: NavDestinationContext | "navBar",
operation: NavigationOperation, animated: boolean) => {
}
})
This content originally appeared on DEV Community and was authored by 程序员一鸣

程序员一鸣 | Sciencx (2025-06-30T04:48:16+00:00) HarmonyOS Development: This article explores the Navigation routing component. Retrieved from https://www.scien.cx/2025/06/30/harmonyos-development-this-article-explores-the-navigation-routing-component/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.