鸿蒙:Navigation的基本使用

注:本章只是简单介绍一下其用法,详情请看官方文档:

Navigation:文档中心

1. Navigation:

Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。

NavRouter :导航组件,默认提供点击响应处理,不需要开发者自定义点击事件逻辑。必须包含两个子组件,其中第二个子组件必须为NavDestination

NavDestination: 作为子页面的根容器,用于显示Navigation的内容区。

1.1 Navigation + NavRouter + NavDestination实现组件跳转(API9)

Navigation内书写的是页面的内容,是Navigation实现页面跳转最外层的跟容器,如果嵌套NavRouter,NavRouter下需要嵌套两个子组件,第一个子组件自定义,点击可以跳转到第二个子组件,第二个必须为NavDestination包裹的子组件,用于显示跳转目标组件的内容。详情看代码:

@Entry
@Component
struct NavigationAPI9 {
  build() {
    Column() {
      Navigation() {
        Text('页面1')
        NavRouter() {
          // 只能写一个组件,写的多了,后面替换前面
          Button('按钮1')
          Button('按钮2')
          NavDestination() {
            Text('页面2')
            NavRouter() {
              Button('按钮3')
              NavDestination() {
                Text('页面3')
                NavRouter() {
                  // .....
                }
              }
            }
          }
        }
      }
    }
    .height('100%')
    .width('100%')
  }
}

效果如下:

1.2. Navigation + NavDestination + NavPathStack 实现组件跳转(API10)

首先显示的页面需要用Navigation包裹,其内书写的为首页内容。可以为其设置toolbarConfiguration属性实现类似Tabs组件的效果,设置title设置标题,设置titleMode属性设置标题模式等等。

@State activeName: string = 'tab1'
  build() {
    Navigation() {
      if (this.activeName === 'tab1') {
        NavigationCase1() // 切换的组件
      } else if (this.activeName === 'tab2') {
        NavigationCase2() // 切换的组件
      } else {
        Text('123')
      }
    }
    .height('100%')
    .width('100%')
    .toolbarConfiguration(this.tabBarBuilder) // 设置tabBar
    .navDestination(this.navDestination) // 设置路由容器
    .title(this.titleBuilder, {
      backgroundColor: Color.Blue,
    }) // 设置标题
    .titleMode(NavigationTitleMode.Full) // 标题模式
    .menus(this.NavigationMenus) // 顶部图标
    .hideTitleBar(false) // 是否隐藏标题栏
    .hideNavBar(false) // 是否隐藏导航栏, 隐藏Navigation的导航栏,包括标题栏、内容区和工具栏。
    .backgroundColor(Color.Pink)
  }

如果你想实现跳转,你需要为Navigation组件配置navDestination属性创建路由容器(或者说罗路由出口)。

NavDestination1与NavDestination2为跳转组件。

之后你需要配置NavPathStack页面栈进行跳转(你可以将其理解为控制器)

整体跳转思路,首先展示的为tab切换页,tab1、tab2、tab3, tab1可以通过跳转NavDestination1按钮跳转到name为NavDestination1的页面(看路由容器),到NavDestination1页面,可以通过按钮跳转NavDestination2跳转到页面NavDestination2,这里携带了param参数,到页面NavDestination2可以通过页面栈NavPathStack中的getParamByName进行接收。

注: 跳转的页面,必须由NavDestination组件包裹

详细demo代码:

//------------ NavigationCase主页面-----
import NavDestination1 from './components/NavDestination1'
import NavDestination2 from './components/NavDestination2'
import NavigationCase1 from './components/NavigationCase1'
import NavigationCase2 from './components/NavigationCase2'

@Entry
@Component
struct NavigationCase {
  @State activeName: string = 'tab1'

  // tabs
  @Builder
  tabBarBuilder() {
    Row() {
      ForEach(['tab1', 'tab2', 'tab3'], (item: string) => {
        Column() {
          Image($r('app.media.ic_public_message')).width(24).aspectRatio(1)
          Text(item).fontColor(this.activeName === item ? '#ff00ff0f' : '#000')
        }.onClick(() => {
          this.activeName = item
        })
      })
    }.width('100%').justifyContent(FlexAlign.SpaceAround)
  }

  // 标题
  @Builder
  titleBuilder() {
    Row() {
      Text('title').fontWeight(700)
    }
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }

  // 顶部icon
  @Builder
  NavigationMenus() {
    Row() {
      Image($r('app.media.ic_public_contacts_group'))
        .width(24).aspectRatio(1)
      Image($r('app.media.ic_public_contacts_group'))
        .width(24)
        .height(24)
      Image($r('app.media.ic_public_contacts_group'))
        .width(24)
        .height(24)
    }.width('100%').justifyContent(FlexAlign.SpaceAround)
  }

  // 路由容器
  @Builder
  navDestination(name: string) {
    if (name === 'NavDestination2') {
      NavDestination2()
    } else if (name === 'NavDestination1') {
      NavDestination1()
    }
  }

  //路由栈, (控制跳转)
  @Provide
  navStack: NavPathStack = new NavPathStack()

  build() {
    Navigation(this.navStack) {
      if (this.activeName === 'tab1') {
        NavigationCase1()
      } else if (this.activeName === 'tab2') {
        NavigationCase2()
      } else {
        Text('123')
      }
    }
    .height('100%')
    .width('100%')
    .toolbarConfiguration(this.tabBarBuilder) // 设置tabBar
    .navDestination(this.navDestination) // 设置路由容器
    .title(this.titleBuilder, {
      backgroundColor: Color.Blue,
    }) // 设置标题
    .titleMode(NavigationTitleMode.Full) // 标题模式
    .menus(this.NavigationMenus) // 顶部图标
    .hideTitleBar(false) // 是否隐藏标题栏
    .hideNavBar(false) // 是否隐藏导航栏, 隐藏Navigation的导航栏,包括标题栏、内容区和工具栏。
    .backgroundColor(Color.Pink)
  }
}

// ------------- NavigationCase1 : tab页面1 --------------
@Component
struct NavigationCase1 {
  @Consume navStack: NavPathStack

  build() {
    Column() {
      Text('tab1')
      Button('跳转NavDestination1').onClick((event: ClickEvent) => {
        this.navStack.pushPath({
          name: 'NavDestination1'
        })
      })
    }
  }
}

export default NavigationCase1

// ------------- NavigationCase1 : tab页面2 --------------
@Component
struct NavigationCase2 {
  build() {
    Column() {
      Text('tab2')
    }
  }
}

export default NavigationCase2

// -----------跳转页面1 -----------------
@Component
struct NavDestination1 {
  @Consume navStack: NavPathStack

  build() {
    NavDestination() {
      Column() {
        Text('页面1')
        Button('跳转NavDestination2').onClick(() => {
          const param: Record<string, string> = {
            'dec': '跳转NavDestination2'
          }
          this.navStack.pushPath({
            name: 'NavDestination2',
            param
          })
        })
      }
    }.title('页面1')
  }
}

export default NavDestination1

// -----------跳转页面2 -----------------
import { promptAction } from '@kit.ArkUI'

@Component
struct NavDestination2 {
  @Consume navStack: NavPathStack

  aboutToAppear(): void {
    promptAction.showDialog({
      message: JSON.stringify(this.navStack.getParamByName('NavDestination2'))
    })
  }

  build() {
    NavDestination() {
      Column() {
        Text('页面2')
      }
    }.title('页面2').hideTitleBar(true)

  }
}

export default NavDestination2

2. 页面跳转

通过NavPathStack控制页面路由,实现跳转,返回,移除页面栈等

2.1 普通跳转

普通跳转,通过页面的name去跳转,并可以携带param。

  1. this.pageStack.pushPath({ name: "PageOne", param: "PageOne Param" })
  2. this.pageStack.pushPathByName("PageOne", "PageOne Param")

 2.2 带返回回调的跳转,跳转时添加onPop回调,能在页面出栈时获取返回信息,并进行处理。

 

this.pageStack.pushPathByName('PageOne', "PageOne Param", (popInfo) => {
console.log('Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result))
});

2.3 带错误码的跳转,跳转结束会触发异步回调,返回错误码信息。

this.pageStack.pushDestinationByName('PageOne', "PageOne Param")
.catch((error: BusinessError) => {
    console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
}).then(() => {
console.error('Push destination succeed.');
});

3. 参数获取

// size: 获取页面栈大小
this.pageStack.size()
// 获取栈中所有页面name集合
// 获取【栈中】所有NavDestination页面的名称。
this.pageStack.getAllPathName()
// 获取【指定index】的NavDestination页面的参数信息。
this.pageStack.getParamByIndex(index)
// 获取全部name为PageOne的NavDestination页面的参数信息。
this.pageStack.getParamByName("PageOne")
// 获取全部name为PageOne的NavDestination页面的位置索引。
this.pageStack.getIndexByName("PageOne")

4. 页面返回、替换、删除

// 返回到上一页
this.pageStack.pop()
this.pageStack.removeByIndexes([this.pageStack.size-1])
// 返回到上一个PageOne页面
this.pageStack.popToName("PageOne")
// 返回到索引为1的页面
this.pageStack.popToIndex(1)
// 返回到根首页(清除栈中所有页面)
this.pageStack.clear()

// 将栈顶页面替换为PageOne
this.pageStack.replacePath({ name: "PageOne", param: "PageOne Param" })
this.pageStack.replacePathByName("PageOne", "PageOne Param")

// 删除栈中name为PageOne的所有页面
this.pageStack.removeByName("PageOne")
// 删除指定索引的页面
this.pageStack.removeByIndexes([1,3,5])

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值