在官网文档有一篇文章介绍了如何实现跨模块的页面跳转 ,链接如下,

如何实现跨模块的页面跳转功能

本篇文章负责提供方案3

第一步,新建两个feature模块

第二步,在feature模块封装组件

封装过程可以分为以下几个步骤:

  1. 定义组件 featureOne:
    使用 @Component 注解创建 featureOne,它包含 UI 构建逻辑,设置文本内容和样式。

  2. 定义构建函数 getFeatureOne:
    @Builder 注解标记,传入参数 name,当值为 'featureOne' 时,调用 NavDestination 加载 featureOne 组件。

  3. 封装为 WrappedBuilder:
    使用 wrapBuildergetFeatureOne 封装为通用的 WrappedBuilder 对象,允许在外部灵活调用。

  4. 完成封装:
    通过这些步骤,构建了一个动态加载的、可复用的组件和函数结构,提升了代码的可扩展性。

问题:为什么要封装成 wrapBuilder?

当你将这些使用了 @Builder 装饰器的函数作为参数传递给其他地方(如导航或者其他组件构建器)时,@Builder 的特性不会被一起传递。这意味着,尽管这些函数原本是用于构建 UI 组件的,但在传递过程中,它们丢失了 @Builder 的信息,导致 UI 校验无法识别该函数的构建能力,不能正常使用这些方法去渲染 UI。

解决方案

系统提供了一个 wrapBuilder 函数,它的作用是将已经使用了 @Builder 装饰的函数再次封装,使它们在传递时保留 @Builder 的特性。通过调用 wrapBuilder,这些组件可以正确传递并在 UI 中被识别和渲染。

第三步,在index将模块导出

第四步,在Entry模块设置依赖

在工程配置文件里配置对feature模块的依赖

依赖格式为:

"@ohos/模块名": 'file:模块路径',

第五步,自定义路由表

在Entry里定义一个路由管理类,使用单例模式。(路由管理类也可单独写在一个新模块,这样各个模块可以相互跳转,而不是只有entry跳转到feature,我这里偷点懒)

路由管理类使用了一个 Map 数据结构来存储和管理不同的对象,其中 key 是一个字符串(路由的路径或名称),value 是对应的对象(可以理解为需要加载的组件或功能模块)。

第六步,实现模块间的路由跳转

在Entry模块的Index里,

​
import { RouterModule } from '../../common/RouterModule';

@Entry
@Component
struct Index {
  // 定义状态变量 pageInfos,用于保存导航路径堆栈
  @State pageInfos: NavPathStack = new NavPathStack()

  // 功能模块列表,用于展示并实现跳转
  featureList: string[] = ['featureOne', 'featureTwo']

  /**
   * 构建页面映射方法,通过传入的名称来获取对应的页面构建器,
   * 如果存在对应的页面构建器,则调用其构建方法。
   * 
   * @param name 要跳转的功能模块名称
   */
  @Builder
  PagesMap(name: string) {
    // 检查 RouterModule 中是否存在对应的功能模块
    if ((RouterModule.getContext().getObject(name)) !== undefined) {
      // 获取功能模块并调用其 builder 方法来进行构建
      (RouterModule.getContext().getObject(name) as WrappedBuilder<[string]>).builder(name)
    }
  }

  /**
   * 构建页面的 UI 结构,包含导航和功能模块列表。
   * 
   * @returns 构建的页面内容
   */
  build() {
    Column() {
      // 导航组件,使用 pageInfos 作为导航堆栈
      Navigation(this.pageInfos) {
        // 显示顶部文本“Entry”
        Text('Entry')
          .fontSize(30)

        // 列表组件,显示 featureList 中的每一个功能模块名称
        List() {
          // 遍历 featureList,生成对应的 ListItem
          ForEach(this.featureList, (item: string) => {
            ListItem() {
              // 显示每个功能模块名称的文本
              Text(item)
                .width('80%')          // 设置文本宽度
                .height(80)            // 设置文本高度
                .borderRadius(20)      // 设置圆角
                .fontSize(20)          // 设置字体大小
                .textAlign(TextAlign.Center)  // 文本居中对齐
                // 当点击某个模块时,导航堆栈中推入该路径
                .onClick(() => {
                  this.pageInfos.pushPathByName(item, '');
                })
            }
          })
        }
      }
      // 设置导航模式为堆栈模式
      .mode(NavigationMode.Stack)
      // 设置标题模式为缩略标题模式
      .titleMode(NavigationTitleMode.Mini)
      // 设置导航栏的标题
      .title('feature模块跳转演示')
      // 使用 PagesMap 作为导航目的地的构建器
      .navDestination(this.PagesMap)
    }
    .width('100%')  // 设置整个页面的宽度为100%
    .height('100%') // 设置整个页面的高度为100%
  }
}

​

这个方案实现路由的关键便是这个 .navDestination()属性

 

根据官方文档里,这个属性接收一个@builder函数,这个@builder 接收组件名并跳转到组件, 大致情况就是,当触发跳转事件时,

this.pageInfos.pushPathByName(item,''),这个pushPathByName方法传入的组件名name会根据这个属性配置找到这个builder函数,name作为参数,调用@builder函数构建组件。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐