Native Harmony Router-Navigation Summary

Navigation route navigation

Use Navigation to replace all route jumps

The concept is: the entire application has only one page, and the rest are components [Huawei recommends using Navigation route navigation]

The first routing method

The outermost layer of the root component must be wrapped by Navigation
The component to be redirected must be wrapped by NavDestination
The redirection object is the NavPathStack object
NavPathStack must be bound to Navigation
The lower-level components use various methods to obtain the upper-level NavPathStack for redirection
The redirection maintenance is implemented by .navDestination
Navigation is bound to NavPathStack, and it is best to use Provide to provide it to child components for use
Route management — bind .navDestination(builder) to Navigation — builder cannot write bracket mode

import { Friend } from './Friend'
 import { Live } from './Live'
 import { Shake } from './Shake'@Entry
 @Component
 struct NavigationCase {
   @Provide
   stackPath: NavPathStack = new NavPathStack()
 ​
 ​
   @Builder
   getRouterBuilder (name: string) {
    // name is the identifier to jump to
     if(name === 'friend') {
       Friend()
     }
     else if(name === "live") {
      Live()
     }
     else if(name === "shake") {
      Shake()
     }
   }
 ​
   build() {
     // 1. Use Navigation to wrap the entire root component
     Navigation(this.stackPath) {
        List() {
          ListItem(){
            Text("朋友圈")
              .fontSize(20)
              .width("100%")
          }
          .height(50)
          .width("100%")
          .padding({
            left: 20
          })
          .onClick(() => {
            this.stackPath.pushPath({
              name: 'friend'
            })
          })
 ​
          ListItem(){
            Text("直播")
              .fontSize(20)
              .width("100%")
          }
          .height(50)
          .width("100%")
          .padding({
            left: 20
          })
          .onClick(() => {
            this.stackPath.pushPath({
              name: 'live'
            })
          })
          ListItem(){
            Text("摇一摇")
              .fontSize(20)
              .width("100%")
          }
          .height(50)
          .width("100%")
          .padding({
            left: 20
          })
          .onClick(() => {
            this.stackPath.pushPath({
              name: 'shake'
            })
          })
        }
        .divider({
          strokeWidth: 2,
          color: "#ccc"
        })
     }
     .navDestination(this.getRouterBuilder)
     .mode(NavigationMode.Auto)
 ​
   }
 }
import { IParams } from "./NavigationCase"@Component
 export struct NavigationCase_friend {
   @Consume navStackPath: NavPathStack
   @State age: number = 0
   @State name: string = ''
 ​
   build() {
     NavDestination() {
       Text("朋友圈")
       Button("点我返回上一页")
         .onClick(() => {
           this.navStackPath.pop()
         })
 ​
       Text(this.name + this.age)
 ​
     }.onWillAppear(() => {
       const params = this.navStackPath.getParamByName('friend') as IParams[]
       this.age = params[params.length - 1]?.age
       this.name = params[params.length - 1]?.name
       AlertDialog.show({ message: JSON.stringify(params, null, 2) })
     })
   }
 }

The second way: WrapBuilder

wrapBuilder can wrap a global builder, which will not be rendered immediately, and needs to run the builder method directly

Subcomponents need to export the global builder separately

WrapBuilder

wrapBuilder is a global function

It will return a type of WrapBuilder<[]>, the empty array is the type of the parameter

map.get(name).builder()
import { FriendPageBuilder } from "./NavigationCase_friend"
 import { LivePageBuilder } from "./NavigationCase_live"
 import { LookPageBuilder } from "./NavigationCase_look"export const RouterMap: Map<string, WrappedBuilder<[]>> = new Map()
 ​
 RouterMap.set("look", wrapBuilder(LookPageBuilder))
 RouterMap.set("live", wrapBuilder(LivePageBuilder))
 RouterMap.set("friend", wrapBuilder(FriendPageBuilder))
@Component
 export struct NavigationCase_look {
   @Consume navStackPath: NavPathStack
 ​
   build() {
     NavDestination() {
       Text("看一看")
       Button("点我去到live")
         .onClick(() => {
           this.navStackPath.pushPath({ name: 'live' })
         })
 ​
       Button("返回到根首页")
         .onClick(() => this.navStackPath.clear())
     }
   }
 }
 ​
 @Builder
 export function LookPageBuilder() {
   NavigationCase_look()
 }
import { RouterMap } from './NavigationCase_WrapBuilder'export interface IParams {
   name: string
   age: number
 }
 ​
 @Entry
 @Component
 struct NavigationCase {
   @Provide navStackPath: NavPathStack = new NavPathStack()
 ​
   @Builder
   getBuilder(name: string) {
     RouterMap.get(name)?.builder()
   }
 ​
   build() {
     Navigation(this.navStackPath) {
       List({ space: 20 }) {
         ListItem() {
           Text("朋友圈")
             .width("100%")
             .height(60)
             .backgroundColor(Color.Pink)
         }.onClick(() => {
           this.navStackPath.pushPath({ name: 'friend', param: { name: 'aaa', age: 18 } as IParams })
         })
 ​
         ListItem() {
           Text("直播")
             .width("100%")
             .height(60)
             .backgroundColor(Color.Brown)
         }
         .onClick(() => {
           this.navStackPath.pushPath({ name: 'live' })
         })
 ​
         ListItem() {
           Text("看一看")
             .width("100%")
             .height(60)
             .backgroundColor(Color.Orange)
         }
         .onClick(() => {
           this.navStackPath.pushPathByName('look', null)
         })
       }
     }
     .mode(NavigationMode.Auto)
     .navDestination(this.getBuilder)
   }
 }

The third method: configuration routing

The root component must be wrapped by Navigation
Must be bound to NavStackPath
Subcomponents must be wrapped by NavDestination
There must be a global builder to render subcomponents
No need to configure .navDestination
A routerMap json file [“routerMap”: “$profile:router_map”] needs to be configured in the project’s module.json5
Configure three contents in the routerMap file — name-builder-file path
The route map mode can only be tested in the simulator

{
   "routerMap": [
     {
       "name": "main",
       "buildFunction": "MainPageBuilder",
       "pageSourceFile": "src/main/ets/pages/AgainNavigation/MainPage.ets"
     },
     {
       "name": "detail",
       "buildFunction": "PageDetailBuilder",
       "pageSourceFile": "src/main/ets/pages/AgainNavigation/PageDetail.ets"
     }
   ]
 }

Navigation parameter — Return — Return to the first page

this.stackPath.getParamByName(“当前页的name”)

.onWillAppear(() => {
      const params =  this.stackPath.getParamByName("detail") as Params[]
       this.age = params[params.length - 1]?.age
      console.log("onWillAppear")
    })

If no parameters are passed, the array still has a length, but the content is undefined
Return to home page: this.stackPath.popToIndex(-1)
Return to previous page: this.stackPath.pop()
// Return to the previous PageOne page // this.pageStack.popToName(“PageOne”)
// Return to the root home page (clear all pages in the stack) // this.pageStack.clear()

pushPath (append)/replacePath (replace), unlimited layers
router-32 layers
pushPath({ name: ‘’, param: 123 }), assuming that the object to be passed must be of a specific type, such as interface/class/Record/Map
receive parameter this.stackPath.getParamByName(“xx”) — xx is the name value of the current component
the parameter type obtained is an unknown[], forcing developers to perform as specific type[]
to take the last parameter — if no parameter is passed, the array still exists, but the content is undfined

Some common properties of the Navigation component

.title() // Title, you can set a custom builder
.titleMode() // Set the page title bar display mode, common properties:
NavigationTitleMode.Mini
.hideTitleBar(true) // Hide the title bar
.mode() // Set the display mode of the navigation bar, commonly used Stack, no column display
.navDestination() // Create a NavDestination component. Use the builder function to construct a NavDestination component based on name and param. There can only be one root node under the builder. The builder allows a layer of custom components outside the NavDestination component, but custom components are not allowed to set properties and events, otherwise they will only display blank.

Recommendations for NavDestination Components

It is not recommended to set layout-related properties such as position and size, as this may cause abnormal page display.

0
Subscribe to my newsletter

Read articles from 白菜炖鱼只喝汤 directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

白菜炖鱼只喝汤
白菜炖鱼只喝汤