风雨同行 发表于 2024-12-19 03:37:04

HarmonyOS Navigation路由组件使用

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

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

可以通过Navigation onNavBarStateChange函数监听当前页面(Navigation根节点)的显示和隐蔽,通过@State注解的字段传递给TabContent组件,让TabContent可以观察页面的显示和隐蔽状态。
@Entry
@Component
struct Index {
@Provide indexPathStack: NavPathStack = new NavPathStack()
//当前选中的下标
@State currentIndex: number = 0
private tabsController: TabsController = new TabsController();
@State onPageResume: boolean = false

aboutToAppear(): void {
    console.info('Index aboutToAppear')
}

/**
   * 应用前后台显示
   */
onPageShow(): void {
    console.info('Index onPageShow')
}

/**
   * 应用前后台隐藏
   */
onPageHide(): void {
    console.info('Index onPageHide')
}

@Builder
tabBarBuilder(title: string, targetIndex: number, selectIcon: Resource, unSelectIcon: Resource) {
    ......

}

build() {
    Navigation(this.indexPathStack) {
      Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
      TabContent() {
          Home()
      }
      .tabBar(this.tabBarBuilder('首页', 0, $r('app.media.ic_home_on'), $r('app.media.ic_home_off')))

      TabContent() {
          Mine({ onPageResume: this.onPageResume })
      }.tabBar(this.tabBarBuilder('我的', 1, $r('app.media.ic_mine_on'), $r('app.media.ic_mine_off')))
      }
      .vertical(false)
      .divider({ strokeWidth: 0.5, color: '#0D182431' })
      .scrollable(false)
      .backgroundColor('#F1F3F5')
    }
    .mode(NavigationMode.Stack)
    .hideTitleBar(true)
    // .hideToolBar(true)
    .backgroundColor("#FFFFFF")
    .onNavBarStateChange((isVisible: boolean)=>{
      //Navigation组件,根节点如何监听隐藏与展示,监听页面占中的显示和隐藏,上个页面返回的时候会触发,https://www.wzhi.top/?id=25
      console.info(`onNavBarStateChange isVisible=${isVisible}`)
      this.onPageResume = isVisible
    })
}
} 二、Navigation子页面NavDestination实现页面显示隐蔽的监听

Navigation的子页面必要获得栈变量并进行栈的操作,Index.ets的栈变量
@Consume indexPathStack: NavPathStack; 子页面的实现:

@Preview
@Component
export struct Mine {
@State isLogin: boolean = false
@State userInfo: UserInfo = {
    avatar: $r('app.media.ic_default_avatar'),
    nickname: '未登录'
}
@Consume indexPathStack: NavPathStack;
isFirstShow: boolean = true;
@Prop @Watch('onPageResumeChange') onPageResume: boolean

/**
   * 监听页面课件状态,onPageResume 由Index.ets页面传递过来
   */
onPageResumeChange() {
    console.info(`Mine onPageResumeChange this.onPageResume=${this.onPageResume}isFirstShow=${this.isFirstShow}`)
    if (this.isFirstShow) {
      this.isFirstShow = false
      return
    }

    if (this.onPageResume) {
      this.getLocalUserInfo()
    }
}

/**
   * 在创建自定义组件后,执行其build()函数之前执行(NavDestination创建之前),允许在该方法中改变状态变量,更改将在后续执行build()函数中生效。
   */
aboutToAppear(): void {
    console.info('mine aboutToAppear')
    this.getLocalUserInfo()
}

getLocalUserInfo() {
    ......
}

build() {
    NavDestination() {
      Column() {
      ......
      }
      .width('100%')
      .height('100%')
      .backgroundColor('#F5F5F5')
    }
    .mode(NavDestinationMode.STANDARD)
    .hideTitleBar(true)
    .onShown(() => {
      console.info('Mine onShown')
    }).onHidden(() => {
      console.info('Mine onHidden')
    })

}

@Builder
MenuItem(
    icon: Resource,
    title: string,
    onClick: () => void
) {
    ......
}
}
可以通过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这个变量来进行页面路由
@Entry
@Component
struct Index {
@Provide indexPathStack: NavPathStack = new NavPathStack()


@Builder
tabBarBuilder(title: string, targetIndex: number, selectIcon: Resource, unSelectIcon: Resource) {
......

}

build() {
    Navigation(this.indexPathStack) {
      Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
      ......
      }
      .vertical(false)
      .divider({ strokeWidth: 0.5, color: '#0D182431' })
      .scrollable(false)
      .backgroundColor('#F1F3F5')
    }
    .mode(NavigationMode.Stack)
    .hideTitleBar(true)
    // .hideToolBar(true)
    .backgroundColor("#FFFFFF")
    .onNavBarStateChange((isVisible: boolean)=>{
      //Navigation组件,根节点如何监听隐藏与展示,监听页面占中的显示和隐藏,上个页面返回的时候会触发,https://www.wzhi.top/?id=25
      console.info(`onNavBarStateChange isVisible=${isVisible}`)
      this.onPageResume = isVisible
    })
}
} 2、NavDestination接收indexPathStack这个变量来进行页面路

由NavDestination接收indexPathStack这个变量来进行页面路由。
通过 @Consume indexPathStack: NavPathStack 来获取Navigation传递过来的路由栈变量,在onClick中调用this.indexPathStack.pushPathByName 实现页面的跳转。当然参数中的name必要进行配置,接着往下看。

@Preview
@Component
export struct Mine {

@Consume indexPathStack: NavPathStack;


getLocalUserInfo() {
   ......
}

build() {
    NavDestination() {
      Column() {
      // 顶部用户信息区域
      Row() {
          Image(this.userInfo.avatar)
            .width(80)
            .height(80)
            .borderRadius(40)
            .margin({ right: 20 })
            .onClick(() => {
            if (!this.isLogin) {
                console.info('跳转到登录页面')
                this.indexPathStack.pushPathByName('PageLogin', null, true)
            }
            })

            ......
      }
      .width('100%')
      .padding(20)
      .backgroundColor('#FFFFFF')

      
      }
      .margin({ top: 12 })
      .backgroundColor('#FFFFFF')
      }
      .width('100%')
      .height('100%')
      .backgroundColor('#F5F5F5')
    }
    .mode(NavDestinationMode.STANDARD)
    .hideTitleBar(true)
    .onShown(() => {
      console.info('Mine onShown')
    }).onHidden(() => {
      console.info('Mine onHidden')
    })

}

@Builder
MenuItem(
    icon: Resource,
    title: string,
    onClick: () => void
) {
   ......
}
}
3、在src/main/resources/base/profile目录下面创建route_map.json文件,进行路由页面的配置

{
"routerMap": [
    {
      "name": "PageLogin",//自定义组件的名称
      "pageSourceFile": "src/main/ets/components/login.ets",//自定义组件所在的.ets文件的路径
      "buildFunction": "PageLoginBuilder",//路由目标页面需要实现这个方法,调用PageLogin(),才能实现最终的路径
      "data": {
      "description" : "this is Page Login"//当前路由的描述

      }
    },
    {
      "name": "RegisterPage",
      "pageSourceFile": "src/main/ets/components/register.ets",
      "buildFunction": "PageRegisterBuilder",
      "data": {
      "description" : "this is Page register"
      }
    },
    {
      "name": "SettingPage",
      "pageSourceFile": "src/main/ets/components/setting.ets",
      "buildFunction": "PageSettingBuilder",
      "data": {
      "description" : "this is Page setting"
      }
    }
]
} 4、路由目的页面实现,以登录页面为例


// 跳转页面入口函数,路由配置中配置的函数名称
@Builder
export function PageLoginBuilder() {
LoginPage()
}

@Component
struct LoginPage {
@State username: string = ''
@State password: string = ''
@State isLoading: boolean = false
@Consume indexPathStack: NavPathStack

build() {
    NavDestination() {
      Column() {
      

      }
      .width('100%')
      .height('100%')
      .backgroundColor('#FFFFFF')
    }
    .hideTitleBar(true)
    .onShown( ()=>{//页面显示的监听
      console.info('login onShow')
    })
    .onHidden(()=>{//页面隐藏的监听
      console.info('login onHidden')
    })
}

private handleLogin() {
    ......
}
}

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: HarmonyOS Navigation路由组件使用