鸿蒙应用中的页面跳转分析

在鸿蒙应用中,自API 11开始可以采用 Navigation 组件进行跳转,分析如下。

1 在Index.ets文件中

scss 复制代码
@Entry   
@Component   
struct Index {
  store: IndexStore = new IndexStore()
@State
  state?: IndexState = undefined

  aboutToAppear(): void {
    this.store.observe((state) => {
      this.state = state
    })
	// 应用启动时,在 aboutToAppear 生命周期方法中,默认跳转到 OverviewPage 页面,使用 replacePath 方法替换当前页面,而不是添加新页面到栈中.
    this.router.replacePath({
      name: 'OverviewPage'
    })
  }

  aboutToDisappear(): void {
    this.store.clear()
  }

  // 使用 @Provide router: NavPathStack = new NavPathStack() 创建了一个全局共享的导航栈实例
  // 通过HarmonyOS的状态共享机制,该 router 实例可以在所有子组件中通过 @Consume router 访问
  // 这实现了跨组件层级的导航状态共享, @Provide 实现 "跨层级组件的状态共享",与 @Consume 配对,解决 "层层传参" 问题,支持状态双向同步。
  // @Provide 本质是鸿蒙 ArkTS 语言为 "状态管理" 设计的基础装饰器,定义在 @ohos.ui.components 模块中(ArkUI 的核心组件与装饰器模块)。
  // ArkTS 会自动引入 "状态管理相关的基础装饰器"(包括 @Provide、@Consume、@State、@Prop 等),只要代码是 ArkUI 组件(用 @Component 装饰),就能直接使用 @Provide,无需额外导入步骤。
  // @Provide 不能单独使用,必须与子组件的 @Consume 配对 ------@Provide 是 "状态提供者",@Consume 是 "状态订阅者",二者通过相同的 "状态标识"(默认是变量名,也可自定义) 关联
  // 可自定义 "状态标识"(避免同名冲突),如果多个 @Provide 变量名相同(如不同组件都有 router),可通过 @Provide('标识名') 自定义标识,子组件用 @Consume('标识名') 匹配:
  // 父组件:自定义标识为"appRouter", @Provide('appRouter') router: NavPathStack = new NavPathStack();
  // 子组件:通过标识"appRouter"订阅,避免与其他同名状态冲突,@Consume('appRouter') router: NavPathStack;
  @Provide
  router: NavPathStack = new NavPathStack() // 创建路由栈(NavPathStack),用@Provide共享给子组件

  @State
  index?: number = undefined

  // tabNames :存储标签页显示文本的数组
  tabNames: string[] = [
    'A操作', 'B数据', 'C显示', 'D监控'
  ]

  // routeNames :存储标签页对应的页面名称的数组,这两个数组通过索引位置一一对应,实现了标签到页面的映射
  routeNames: string[] = [
    'AView', 'BView', 'CView', 'DView'
  ]

  build() {
    Column() {
	  // Column() 组件是 垂直布局容器 ,会将所有子组件沿垂直方向(从上到下)排列
      Column() {
	    // 通过 IndexTabView 的 onChange 回调监听标签页切换,根据选中的标签索引,从 routeNames 数组中获取对应的页面名称
		// 在各个子页面中(如 IPManageView ),可以通过 @Consume 的router实例调用 pushPath 等方法进行页面跳转
        IndexTabView({
          index: this.index,
          tabs: this.tabNames,
          onChange: (index) => {
            this.index = index
            if (index !== undefined) {
			  // 使用 router.replacePath 方法切换到对应的页面
			  // 当使用this.router.replacePath()或this.router.pushPath()进行页面跳转时,Navigation组件会调用 navDestination 属性指定的PagesRouter函数,PagesRouter根据传入的路由名称参数,动态构建并渲染对应的视图组件
              this.router.replacePath({
                name: this.routeNames[index]
              }, false)
            } else {
			  // 当索引无效时,回退到 OverviewPage 页面
              this.router.replacePath({
                name: 'OverviewPage'
              }, false)
            }
          }
        })
        Blank()
          .height('10px')
		// Row() 组件是 水平布局容器 ,会将所有子组件沿水平方向(从左到右)排列
        Row() {
          OverviewActionView({
            onActionClick: (action) => {
              this.store.performAction(action)
            }
          })
		  // 右侧放置 Navigation 组件(主要内容显示区域), 
		  // Navigation 组件:通过@Provide/@Consume或NavController共享NavPathStack
		  // Navigation是 Stage 模型的导航容器组件,NavPathStack是管理路径的 "栈容器",二者配合实现路由,支持组件级导航、自定义标题栏、动画过渡等,是你之前代码中使用的方案。
          Navigation(this.router) // 绑定路由栈到Navigation组件
          .hideTitleBar(true)
          .mode(NavigationMode.Stack) // 配置为栈式导航模式( NavigationMode.Stack )
          .navDestination(this.PagesRouter) // 通过 navDestination 属性关联了 PagesRouter 构建器函数, 也即是绑定页面构建器(路径→组件映射)
          .layoutWeight(1)
          .height('100%')
          .backgroundColor(Color.Transparent)
        }
        .layoutWeight(1)
        .alignItems(VerticalAlign.Top)
        .padding({  bottom: '10px'})
      }
      .layoutWeight(1)
      .padding({ left: '9px', right: '9px' })
    }
    .width('100%')
    .height('100%')
    .backgroundImage($r("app.media.bg_window"))
    .backgroundImageSize({ width: '100%', height: '100%' })
  }

  // PagesRouter 是一个 @Builder 装饰的函数,用于根据页面名称动态创建对应的组件实例,它是整个应用页面路由的核心映射机制.
  // @Builder是HarmonyOS ArkUI框架中的UI构建函数装饰器,具有以下特点:
  //组件构建封装:将UI组件的创建逻辑封装在函数中,实现组件复用和逻辑分离
  //动态UI构建:根据传入参数动态决定构建哪种UI组件
  //编译期优化:Builder函数在编译期会被优化处理,提升渲染性能
  //无返回值:Builder函数不需要显式返回UI组件,直接在函数体内声明组件即可
  @Builder
  PagesRouter(name: string) { // 页面构建器:路径名→页面组件的映射
    if (name === 'AView') {
      AView()
    } else if (name === 'OverviewPage') {
      OverviewPage()
    }
  }
}

2 分析路由的发布与订阅的联系

在Index.ets中

less 复制代码
@Provide
router: NavPathStack = new NavPathStack()

在AView.ets中

css 复制代码
@Consume
router: NavPathStack

两者的联系 :

在 Index.ets 中定义了 @Provide router: NavPathStack = new NavPathStack()。

在 IPManageView.ets 中,使用 @Consume router: NavPathStack 进行消费。

这是HarmonyOS中的状态共享机制,@Provide 装饰的变量可以在其组件树的子组件中被 @Consume 装饰的变量共享和访问。它们共享同一个NavPathStack实例,用于应用内的页面导航。

命名规则 :

默认情况下,@Provide和@Consume需要使用相同的变量名来建立绑定关系,比如两者都使用了"router"作为变量名。

也可以使用相同的别名来建立绑定,可以使用 @Provide('myRouter') router: NavPathStack 和 @Consume('myRouter') customRouter: NavPathStack

这样即使变量名不同,通过共享的别名'myRouter'也能建立正确的绑定关系。

这种机制实现了组件树中跨层级的数据共享,避免了逐层传递参数的复杂性,特别适合用于全局状态管理如导航栈。

3 在BView中应用NavDestination

scss 复制代码
build() {  
NavDestination() {    
Row() {      
...    }  
}  .hideTitleBar(true)  .backgroundColor(Color.Transparent)}

在BView中的 build 函数中使用 NavDestination 包裹整个BView页面。

在BView.ets文件中,build方法使用NavDestination()包裹整个页面内容,这是HarmonyOS ArkUI框架中导航系统的重要设计模式。

使用NavDestination的原因

3.1 导航系统的层次关系

在Index.ets中,项目使用了完整的导航栈架构:

less 复制代码
@Provide
router: NavPathStack = new NavPathStack()
// 在UI中Navigation(this.router)  .hideTitleBar(true)  .mode(NavigationMode.Stack)  .navDestination(this.PagesRouter)

NavDestination作为Navigation的目的地组件,形成了完整的导航层次结构:Navigation(导航容器)→ NavDestination(导航目的地)。

3.2 页面组件的标准化封装

使用NavDestination包裹页面内容的主要原因包括:

导航上下文整合:NavDestination为页面提供了完整的导航上下文,使其能够正确地参与到导航栈的管理中。

路由参数传递支持:便于接收和处理通过路由传递的参数。

生命周期统一管理:保证页面在导航过程中能正确触发组件生命周期方法。

导航状态同步:确保页面状态与导航栈状态保持同步。

3.3 导航机制的实现

Index.ets中使用@Provide定义全局共享的NavPathStack实例。 其它页面使用@Consume获取并使用这个导航栈。 通过this.router.pushPath()进行页面跳转,this.router.pop()返回上一页。

3.4 NavDestination作为被导航到的目标页面容器的技术设计优势

使用NavDestination的设计优势包括:

组件化设计:每个页面作为独立的导航目的地,便于维护和复用。

统一的导航体验:通过Navigation和NavDestination的配合,提供一致的导航体验。

灵活的页面配置:可以通过NavDestination的属性(如.hideTitleBar())自定义页面的导航行为。

状态管理集成:与@State、@Provide、@Consume等状态管理机制无缝集成。

总结来说,BView.ets中build方法使用NavDestination是HarmonyOS ArkUI导航架构的标准实践,确保页面能够正确参与导航栈管理,并与应用的整体导航机制保持一致。

相关推荐
大雷神5 小时前
windows开发中使用flutter开发鸿蒙
华为·harmonyos
Swift社区5 小时前
HarmonyOS 用 attributeModifier 修改按钮背景但按压态不生效
华为·harmonyos
无风听海7 小时前
HarmonyOS之Environment
harmonyos
特立独行的猫a7 小时前
HarmonyOS鸿蒙中的NES游戏模拟器的完整实现
游戏·华为·harmonyos·fc·nes
小雨青年7 小时前
创建你的第一个 HarmonyOS 6 鸿蒙应用 Hello HarmonyOS
华为·harmonyos
猫林老师8 小时前
OpenHarmony内核基础:LiteOS-M内核与POSIX/CMSIS接口
华为·harmonyos
程序员潘Sir9 小时前
鸿蒙应用开发从入门到实战(二十三):一文搞懂ArkUI弹性布局
harmonyos·鸿蒙
猫林老师10 小时前
OpenHarmony南向开发环境搭建 - 深入理解Ubuntu、DevEco Device Tool与HPM
linux·运维·ubuntu·harmonyos·openharmony