纯血鸿蒙NEXT-组件导航 (Navigation)
Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。
路由操作
Navigation路由相关的操作都是基于页面栈NavPathStack提供的方法进行,每个Navigation都需要创建并传入一个NavPathStack对象,用于管理页面。主要涉及页面跳转、页面返回、页面替换、页面删除、参数获取、路由拦截等功能。
一、配置系统路由
1.1 route_map.json
在工程resources/base/profile中创建route_map.json文件。添加如下配置信息:
{
"routerMap": [
{
"name": "PageOne",
"pageSourceFile": "src/main/ets/pages/PageOne.ets",
"buildFunction": "PageOneBuilder"}
]
}
配置说明如下:
配置项 | 说明 |
---|---|
name | 跳转页面名称 |
pageSourceFile | 跳转目标页在包内的路径,相对src目录的相对路径 |
buildFunction | 跳转目标页的入口函数名称,必须以@Builder修饰 |
data | 应用自定义字段。可以通过配置项读取接口getConfigInRouteMap获取 |
1.2 module.json5添加路由表配
在跳转目标模块的配置文件module.json5添加路由表配置:
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone",
"tablet",
"2in1"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
]
}
],
"routerMap": "$profile:route_map"
}
}
二、路由获取
Navigation作为组件,子页面想要做路由需要拿到Navigation持有的页面栈对象NavPathStack,可以通过如下几种方式获取:
方式一:通过@Provide和@Consume传递给子页面(有耦合,不推荐)。
// Navigation根容器
@Entry
@Component
struct Index {
// Navigation创建一个Provide修饰的NavPathStack
@Provide('pathStack') pathStack: NavPathStack = new NavPathStack()
build() {
Navigation(this.pathStack) {
// ...
}
.title("Navigation")
.mode(NavigationMode.Stack)
}
}
// Navigation子页面
@Component
export struct PageOne {
// NavDestination通过Consume获取到
@Consume('pathStack') pathStack: NavPathStack;
build() {
NavDestination() {
// ...
}
.title("PageOne")
}
}
方式二:子页面通过OnReady回调获取
@Component
export struct PageOne {
pathStack: NavPathStack = new NavPathStack()
build() {
NavDestination() {
// ...
}.title('PageOne')
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
})
}
}
方式三: 通过全局的AppStorage接口设置获取
@Entry
@Component
struct Index {
pathStack: NavPathStack = new NavPathStack()
// 全局设置一个NavPathStack
aboutToAppear(): void {
AppStorage.setOrCreate("PathStack", this.pathStack)
}
build() {
Navigation(this.pathStack) {
// ...
}.title("Navigation")
.mode(NavigationMode.Stack)
}
}
// Navigation子页面
@Component
export struct PageOne {
// 子页面中获取全局的NavPathStack
pathStack: NavPathStack = AppStorage.get("PathStack") as NavPathStack
build() {
NavDestination() {
// ...
}
.title("PageOne")
}
}
方式四:通过自定义组件查询接口获取,参考queryNavigationInfo
import { uiObserver } from '@kit.ArkUI';
// 子页面中的自定义组件
@Component
struct CustomNode {
pathStack : NavPathStack = new NavPathStack()
aboutToAppear() {
// query navigation info
let navigationInfo : NavigationInfo = this.queryNavigationInfo() as NavigationInfo
this.pathStack = navigationInfo.pathStack;
}
build() {
Row() {
Button('跳转到PageTwo')
.onClick(()=>{
this.pathStack.pushPath({ name: 'pageTwo' })
})
}
}
}
三、页面跳转
NavPathStack通过Push相关的接口去实现页面跳转的功能,主要分为以下三类:
- 普通跳转,通过页面的name去跳转,并可以携带param。
this.pageStack.pushPath({ name: "PageOne", param: "PageOne Param" })
this.pageStack.pushPathByName("PageOne", "PageOne Param")
- 带返回回调的跳转,跳转时添加onPop回调,能在页面出栈时获取返回信息,并进行处理
this.pageStack.pushPathByName('PageOne', "PageOne Param", (popInfo) => {
console.log('Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result))
});
Index.ets
@Entry
@Component
struct Index {
@State message: string = '下一页';
pathStack: NavPathStack = new NavPathStack()
aboutToAppear(): void {
AppStorage.setOrCreate("PathStack", this.pathStack)
}
build() {
Navigation(this.pathStack){
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
}).onClick(()=>{
this.pathStack.pushPathByName("PageOne","PageOne Param",(popInfo)=>{
this.message=popInfo.result as string
},true)
})
}
.height('100%')
.width('100%')
}
}
}
PageOne.ets
@Builder
export function PageOneBuilder(){
PageOne()
}
@Preview
@Component
struct PageOne{
@State param?:string=""
pathStack: NavPathStack = new NavPathStack()
build() {
NavDestination(){
Column(){
Text(this.param).width(200).height(100).onClick(()=>{
this.pathStack.pop("Page one return")
})
}.width('100%').height("100%")
}.onReady((context:NavDestinationContext) =>{
this.pathStack=context.pathStack
let pathInfo=context.pathInfo
this.param=pathInfo.param as string
})
}
}
- 带错误码的跳转,跳转结束会触发异步回调,返回错误码信息
this.pageStack.pushDestinationByName('PageOne', "PageOne Param")
.catch((error: BusinessError) => {
console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
}).then(() => {
console.info('Push destination succeed.');
});
四、参数获取
4.1 NavPathStack
通过Get相关接口去获取页面的一些参数
// 获取栈中所有页面name集合
this.pageStack.getAllPathName()
// 获取索引为1的页面参数
this.pageStack.getParamByIndex(1)
// 获取PageOne页面的参数
this.pageStack.getParamByName("PageOne")
// 获取PageOne页面的索引集合
this.pageStack.getIndexByName("PageOne")
route_map.json
{
"routerMap": [
{
"name": "PageOne",
"pageSourceFile": "src/main/ets/pages/PageOne.ets",
"buildFunction": "PageOneBuilder"}
]
}
Index.ets
@Entry
@Component
struct Index {
@State message: string = '下一页';
pathStack: NavPathStack = new NavPathStack()
aboutToAppear(): void {
AppStorage.setOrCreate("PathStack", this.pathStack)
}
build() {
Navigation(this.pathStack){
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
}).onClick(()=>{
this.pathStack.pushPathByName("PageOne","PageOne Param",true)
})
}
.height('100%')
.width('100%')
}
}
}
PageOne.ets
@Builder
export function PageOneBuilder(){
PageOne()
}
@Preview
@Component
struct PageOne{
@State param?:string=""
pathStack: NavPathStack = new NavPathStack()
build() {
NavDestination(){
Column(){
Text(this.param).width(200).height(100)
}.width('100%').height("100%")
}.onReady((context:NavDestinationContext) =>{
this.pathStack=context.pathStack
})
}
}
PageOne.ets
@Builder
export function PageOneBuilder(){
PageOne()
}
@Preview
@Component
struct PageOne{
@State param?:string=""
pathStack: NavPathStack = new NavPathStack()
build() {
NavDestination(){
Column(){
Text(this.param).width(200).height(100)
}.width('100%').height("100%")
}.onReady((context:NavDestinationContext) =>{
this.pathStack=context.pathStack
let index=this.pathStack.getIndexByName("PageOne")[0]
this.param=this.pathStack.getParamByIndex(index) as string
})
}
}
getIndexByName
通过路由名获取该页面在栈中的下标,该方法返回的是一个数组
getParamByIndex
通过索引获取传入的参数,需要强转类型
4.2 NavPathInfo
- nane 系统路由表定义的页面名称
- param pathStack传递参数字段
PageOne.ets
@Builder
export function PageOneBuilder(){
PageOne()
}
@Preview
@Component
struct PageOne{
@State param?:string=""
pathStack: NavPathStack = new NavPathStack()
build() {
NavDestination(){
Column(){
Text(this.param).width(200).height(100)
}.width('100%').height("100%")
}.onReady((context:NavDestinationContext) =>{
let pathInfo=context.pathInfo
this.param=pathInfo.param as string
})
}
}
五、页面返回
NavPathStack通过Pop相关接口去实现页面返回功能
// 返回到上一页
this.pageStack.pop()
// 返回到上一个PageOne页面
this.pageStack.popToName("PageOne")
// 返回到索引为1的页面
this.pageStack.popToIndex(1)
// 返回到根首页(清除栈中所有页面)
this.pageStack.clear()