在鸿蒙应用开发中,随着应用功能日益复杂,模块化开发成为主流。Navigation提供了跨包路由能力,支持在不同模块(HAP、HSP、HAR)之间进行页面跳转。

一、路由方式

Navigation提供两种跨包路由实现方式:

路由方式 跨包跳转能力 可扩展性 易用性
系统路由表 跳转前无需import页面文件,页面按需动态加载 可扩展性一般 易用性更强,系统自动维护路由表
自定义路由表 跳转前需要import页面文件 可扩展性更强 易用性一般,需开发者自行维护路由表

说明:支持自定义路由表和系统路由表混用。

二、系统路由表

系统路由表是动态路由的一种实现方式。从API version 12开始,Navigation支持使用系统路由表的方式进行动态路由。从API version 23开始,Navigation组件支持跳转到按需加载的HSP页面。

注意:系统路由表支持模拟器但不支持预览器

实现原理

各业务模块(HAP、HSP、HAR)中需要独立配置router_map.json文件。触发路由跳转时,应用只需要通过NavPathStack提供的路由方法,传入需要路由的页面配置名称,系统会自动完成路由模块的动态加载、页面组件构建,并完成路由跳转。

实现步骤

步骤1:创建router_map.json

在工程resources/base/profile路径下创建router_map.json文件:

{
  "routerMap": [
    {
      "name": "PageOne",
      "pageSourceFile": "src/main/ets/pages/PageOne.ets",
      "buildFunction": "PageOneBuilder",
      "data": {
        "description": "this is PageOne"
      }
    }
  ]
}

字段说明

字段 说明
name 页面名称,用于路由跳转时指定
pageSourceFile 页面源文件路径
buildFunction 页面Builder函数名
data 可选,页面配置数据
步骤2:在module.json5中配置路由表
{
  "module": {
    "routerMap": "$profile:router_map"
  }
}
步骤3:配置页面Builder函数

在跳转目标页面,配置入口Builder函数,函数名需与router_map.json中的buildFunction一致:

// 跳转页面入口函数
@Builder
export function PageOneBuilder() {
  PageOne();
}

@Component
struct PageOne {
  pathStack: NavPathStack = new NavPathStack();
  
  build() {
    NavDestination() {
      // 页面内容
    }
    .title('PageOne')
    .onReady((context: NavDestinationContext) => {
      this.pathStack = context.pathStack;
    })
  }
}
步骤4:执行路由跳转
@Entry
@Component
struct SystemRoutingTable {
  pageStack: NavPathStack = new NavPathStack();
  
  build() {
    Navigation(this.pageStack) {
      // 导航内容
    }
    .onAppear(() => {
      this.pageStack.pushPathByName('PageOne', null, false);
    })
    .hideNavBar(true)
  }
}

三、自定义路由表

自定义路由表通过给Navigation的navDestination属性设置Builder函数实现,其特点是需要import页面

静态import vs 动态import

import方式 模块间耦合度 实现复杂度 性能
动态import 模块间解耦 复杂度高 性能好,按需加载,跳转前再加载对应页面
静态import 模块间耦合 复杂度低 性能一般,初始化时一次性加载所有依赖的页面

建议:推荐使用动态import或系统路由表。

动态import

优势

  1. 路由定义可以配置丰富的扩展信息(横竖屏默认模式、是否需要鉴权等)

  2. 按照名称进行跳转而不是文件路径

  3. 页面的加载可以使用动态import(按需加载),防止首个页面加载大量代码导致卡顿

实现步骤

  1. 定义页面跳转配置项(使用资源文件或ets文件)

  2. 加载目标跳转页面,通过动态import将页面所在模块在运行时加载

  3. 在Navigation的navDestination属性中执行加载的Builder函数

静态import

@Entry
@Component
struct NavigationExample {
  @Provide('navPathStack') navPathStack: NavPathStack = new NavPathStack();
  private arr: number[] = [1, 2];
  
  @Builder
  pageMap(name: string) {
    if (name === 'NavDestinationTitle1') {
      pageOneTmp();
    } else if (name === 'NavDestinationTitle2') {
      pageTwoTmp();
    }
  }
  
  build() {
    Column() {
      Navigation(this.navPathStack) {
        // 导航内容
      }
      .navDestination(this.pageMap)  // 注册路由表
    }
  }
}

@Component
export struct pageOneTmp {
  @Consume('navPathStack') navPathStack: NavPathStack;
  
  build() {
    NavDestination() {
      Column() {
        Text('NavDestinationContent1')
      }
    }
    .title('NavDestinationTitle1')
  }
}

最后

两种路由方式对比

对比项 系统路由表 自定义路由表
import要求 跳转前无需import 跳转前需要import
页面加载 按需动态加载 静态import全量加载 / 动态import按需加载
易用性 更强,系统自动维护 一般,需自行维护
可扩展性 一般 更强
最低版本 API 12 -

选择建议

场景 推荐方案
模块解耦、按需加载 系统路由表
需要扩展路由信息(鉴权等) 自定义路由表(动态import)
简单场景、快速开发 系统路由表
已有静态import实现 静态import(不推荐新项目使用)
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐