HarmonyOS Navigation路由组件使用

打印 上一主题 下一主题

主题 819|帖子 819|积分 2457

Navigation可以作为路由组件来使用
1、可以实现雷同Android startActivityForResult的功能。
2、可以实现页面生命周期函数的回调监听

一、Navigation 根节点监听页面的显示和隐蔽

可以通过Navigation onNavBarStateChange函数监听当前页面(Navigation根节点)的显示和隐蔽,通过@State注解的字段传递给TabContent组件,让TabContent可以观察页面的显示和隐蔽状态。
  1. @Entry
  2. @Component
  3. struct Index {
  4.   @Provide indexPathStack: NavPathStack = new NavPathStack()
  5.   //当前选中的下标
  6.   @State currentIndex: number = 0
  7.   private tabsController: TabsController = new TabsController();
  8.   @State onPageResume: boolean = false
  9.   aboutToAppear(): void {
  10.     console.info('Index aboutToAppear')
  11.   }
  12.   /**
  13.    * 应用前后台显示
  14.    */
  15.   onPageShow(): void {
  16.     console.info('Index onPageShow')
  17.   }
  18.   /**
  19.    * 应用前后台隐藏
  20.    */
  21.   onPageHide(): void {
  22.     console.info('Index onPageHide')
  23.   }
  24.   @Builder
  25.   tabBarBuilder(title: string, targetIndex: number, selectIcon: Resource, unSelectIcon: Resource) {
  26.     ......
  27.   }
  28.   build() {
  29.     Navigation(this.indexPathStack) {
  30.       Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
  31.         TabContent() {
  32.           Home()
  33.         }
  34.         .tabBar(this.tabBarBuilder('首页', 0, $r('app.media.ic_home_on'), $r('app.media.ic_home_off')))
  35.         TabContent() {
  36.           Mine({ onPageResume: this.onPageResume })
  37.         }.tabBar(this.tabBarBuilder('我的', 1, $r('app.media.ic_mine_on'), $r('app.media.ic_mine_off')))
  38.       }
  39.       .vertical(false)
  40.       .divider({ strokeWidth: 0.5, color: '#0D182431' })
  41.       .scrollable(false)
  42.       .backgroundColor('#F1F3F5')
  43.     }
  44.     .mode(NavigationMode.Stack)
  45.     .hideTitleBar(true)
  46.     // .hideToolBar(true)
  47.     .backgroundColor("#FFFFFF")
  48.     .onNavBarStateChange((isVisible: boolean)=>{
  49.       //Navigation组件,根节点如何监听隐藏与展示,监听页面占中的显示和隐藏,上个页面返回的时候会触发,https://www.wzhi.top/?id=25
  50.       console.info(`onNavBarStateChange isVisible=${isVisible}`)
  51.       this.onPageResume = isVisible
  52.     })
  53.   }
  54. }
复制代码
二、Navigation子页面NavDestination实现页面显示隐蔽的监听

Navigation的子页面必要获得栈变量并进行栈的操作,Index.ets的栈变量
  1. @Consume indexPathStack: NavPathStack;
复制代码
子页面的实现:
  1. @Preview
  2. @Component
  3. export struct Mine {
  4.   @State isLogin: boolean = false
  5.   @State userInfo: UserInfo = {
  6.     avatar: $r('app.media.ic_default_avatar'),
  7.     nickname: '未登录'
  8.   }
  9.   @Consume indexPathStack: NavPathStack;
  10.   isFirstShow: boolean = true;
  11.   @Prop @Watch('onPageResumeChange') onPageResume: boolean
  12.   /**
  13.    * 监听页面课件状态,onPageResume 由Index.ets页面传递过来
  14.    */
  15.   onPageResumeChange() {
  16.     console.info(`Mine onPageResumeChange this.onPageResume=${this.onPageResume}  isFirstShow=${this.isFirstShow}`)
  17.     if (this.isFirstShow) {
  18.       this.isFirstShow = false
  19.       return
  20.     }
  21.     if (this.onPageResume) {
  22.       this.getLocalUserInfo()
  23.     }
  24.   }
  25.   /**
  26.    * 在创建自定义组件后,执行其build()函数之前执行(NavDestination创建之前),允许在该方法中改变状态变量,更改将在后续执行build()函数中生效。
  27.    */
  28.   aboutToAppear(): void {
  29.     console.info('mine aboutToAppear')
  30.     this.getLocalUserInfo()
  31.   }
  32.   getLocalUserInfo() {
  33.     ......
  34.   }
  35.   build() {
  36.     NavDestination() {
  37.       Column() {
  38.         ......
  39.       }
  40.       .width('100%')
  41.       .height('100%')
  42.       .backgroundColor('#F5F5F5')
  43.     }
  44.     .mode(NavDestinationMode.STANDARD)
  45.     .hideTitleBar(true)
  46.     .onShown(() => {
  47.       console.info('Mine onShown')
  48.     }).onHidden(() => {
  49.       console.info('Mine onHidden')
  50.     })
  51.   }
  52.   @Builder
  53.   MenuItem(
  54.     icon: Resource,
  55.     title: string,
  56.     onClick: () => void
  57.   ) {
  58.     ......
  59.   }
  60. }
复制代码
可以通过NavDestination的方法.onShown/onHidden监听页面的显示和隐蔽,不过NavDestination是Navigation的跟节点,这个方法就不生效了,比方我再Index.ets中使用了Navigation 嵌套Tabs,TabContent中使用了NavDestination,使用onShown/onHidden就无法被回调,必要在Navigation中使用onNavBarStateChange来监听,把状态传递给TabContent实现页面显示隐蔽的监听。
三、Navigation通过NavPathStack实现页面路由(页面跳转)

1、Navigation实现页面路由,其实是通过NavPathStack的方法来实现的。

可以看到Navigation中传入了参数indexPathStack,类型是NavPathStack,在往下看,是子页面NavDestination接收indexPathStack这个变量来进行页面路由
  1. @Entry
  2. @Component
  3. struct Index {
  4.   @Provide indexPathStack: NavPathStack = new NavPathStack()
  5.   @Builder
  6.   tabBarBuilder(title: string, targetIndex: number, selectIcon: Resource, unSelectIcon: Resource) {
  7.   ......
  8.   }
  9.   build() {
  10.     Navigation(this.indexPathStack) {
  11.       Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
  12.         ......
  13.       }
  14.       .vertical(false)
  15.       .divider({ strokeWidth: 0.5, color: '#0D182431' })
  16.       .scrollable(false)
  17.       .backgroundColor('#F1F3F5')
  18.     }
  19.     .mode(NavigationMode.Stack)
  20.     .hideTitleBar(true)
  21.     // .hideToolBar(true)
  22.     .backgroundColor("#FFFFFF")
  23.     .onNavBarStateChange((isVisible: boolean)=>{
  24.       //Navigation组件,根节点如何监听隐藏与展示,监听页面占中的显示和隐藏,上个页面返回的时候会触发,https://www.wzhi.top/?id=25
  25.       console.info(`onNavBarStateChange isVisible=${isVisible}`)
  26.       this.onPageResume = isVisible
  27.     })
  28.   }
  29. }
复制代码
2、NavDestination接收indexPathStack这个变量来进行页面路

由NavDestination接收indexPathStack这个变量来进行页面路由。
通过 @Consume indexPathStack: NavPathStack 来获取Navigation传递过来的路由栈变量,在onClick中调用this.indexPathStack.pushPathByName 实现页面的跳转。当然参数中的name必要进行配置,接着往下看。
  1. @Preview
  2. @Component
  3. export struct Mine {
  4.   @Consume indexPathStack: NavPathStack;
  5.   getLocalUserInfo() {
  6.    ......
  7.   }
  8.   build() {
  9.     NavDestination() {
  10.       Column() {
  11.         // 顶部用户信息区域
  12.         Row() {
  13.           Image(this.userInfo.avatar)
  14.             .width(80)
  15.             .height(80)
  16.             .borderRadius(40)
  17.             .margin({ right: 20 })
  18.             .onClick(() => {
  19.               if (!this.isLogin) {
  20.                 console.info('跳转到登录页面')
  21.                 this.indexPathStack.pushPathByName('PageLogin', null, true)
  22.               }
  23.             })
  24.             ......
  25.         }
  26.         .width('100%')
  27.         .padding(20)
  28.         .backgroundColor('#FFFFFF')
  29.       
  30.         }
  31.         .margin({ top: 12 })
  32.         .backgroundColor('#FFFFFF')
  33.       }
  34.       .width('100%')
  35.       .height('100%')
  36.       .backgroundColor('#F5F5F5')
  37.     }
  38.     .mode(NavDestinationMode.STANDARD)
  39.     .hideTitleBar(true)
  40.     .onShown(() => {
  41.       console.info('Mine onShown')
  42.     }).onHidden(() => {
  43.       console.info('Mine onHidden')
  44.     })
  45.   }
  46.   @Builder
  47.   MenuItem(
  48.     icon: Resource,
  49.     title: string,
  50.     onClick: () => void
  51.   ) {
  52.    ......
  53.   }
  54. }
复制代码
3、在src/main/resources/base/profile目录下面创建route_map.json文件,进行路由页面的配置

  1. {
  2.   "routerMap": [
  3.     {
  4.       "name": "PageLogin",//自定义组件的名称
  5.       "pageSourceFile": "src/main/ets/components/login.ets",//自定义组件所在的.ets文件的路径
  6.       "buildFunction": "PageLoginBuilder",//路由目标页面需要实现这个方法,调用PageLogin(),才能实现最终的路径
  7.       "data": {
  8.         "description" : "this is Page Login"//当前路由的描述
  9.       }
  10.     },
  11.     {
  12.       "name": "RegisterPage",
  13.       "pageSourceFile": "src/main/ets/components/register.ets",
  14.       "buildFunction": "PageRegisterBuilder",
  15.       "data": {
  16.         "description" : "this is Page register"
  17.       }
  18.     },
  19.     {
  20.       "name": "SettingPage",
  21.       "pageSourceFile": "src/main/ets/components/setting.ets",
  22.       "buildFunction": "PageSettingBuilder",
  23.       "data": {
  24.         "description" : "this is Page setting"
  25.       }
  26.     }
  27.   ]
  28. }
复制代码
4、路由目的页面实现,以登录页面为例

  1. // 跳转页面入口函数,路由配置中配置的函数名称
  2. @Builder
  3. export function PageLoginBuilder() {
  4.   LoginPage()
  5. }
  6. @Component
  7. struct LoginPage {
  8.   @State username: string = ''
  9.   @State password: string = ''
  10.   @State isLoading: boolean = false
  11.   @Consume indexPathStack: NavPathStack
  12.   build() {
  13.     NavDestination() {
  14.       Column() {
  15.         
  16.       }
  17.       .width('100%')
  18.       .height('100%')
  19.       .backgroundColor('#FFFFFF')
  20.     }
  21.     .hideTitleBar(true)
  22.     .onShown( ()=>{//页面显示的监听
  23.       console.info('login onShow')
  24.     })
  25.     .onHidden(()=>{//页面隐藏的监听
  26.       console.info('login onHidden')
  27.     })
  28.   }
  29.   private handleLogin() {
  30.     ......
  31.   }
  32. }
复制代码

完整代码已经上传到gitee:WanHarmony: wanAndroid api 鸿蒙应用

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

风雨同行

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表