Navigation动态路由

介绍

Navigation动态路由运用了WrapperBuilder的自定义函数打包能力,以及动态路由的跨模块文件引用的能力,解除了har包和hap包的依赖关系,实现了 即使hap包不引用har包,依然能跳转到har包中的页面的能力 目前还不支持动态import变量表达式和跨模块相对路径的文件,所以代码中使用switch作为替代。(官方还有一个自定义路由表,由于涉及到自定义装饰器,等有机会在讲)

使用说明

1.创建hapA harA harB

2.创建路由框架RouterModule,使用map存储hap包的路由和har包的页面信息

3.在RouterModule中封装get和set方法,并对外开放,允许外部模块引用和调用

4.创建push方法,允许传入一串url,并对其进行解析,通过拆解出路由名称从map中获取到路由栈,并将目标页面压栈

5.在hap和har包中引入RouterModule,将hap包的路由栈和har包的页面信息通过开放的set方法存入RouterModule

工程目录

├──entry                                          // 入口模块
│  ├──build-profile.json5                         // 编译配置文件,其中arkOptions需配置动态import依赖的包名
│  ├──oh-package.json5                            // 依赖配置,需依赖全部子业务模块和RouterModule模块
│  ├──src/main/ets
│  │  ├──entryability
│  │  │  └──EntryAbility.ets
│  │  └──pages
│  │     └──Index.ets                             // 首页
│  └──src/main/resources                          // 资源目录
├──harA                                           // 子业务模块
│  ├──Index.ets                                   // 入口文件,对外暴露模块方法
│  ├──oh-package.json5                            // 依赖配置,需依赖RouterModule模块
│  ├──src/main/ets/components/mainpage
│  │  ├──A1.ets                                 
│  │  └──A2.ets                                 
│  └──src/main/resources
├──harB                                           // 子业务模块
│  ├──Index.ets                                   // 入口文件,对外暴露模块方法
│  ├──oh-package.json5                            // 依赖配置,需依赖RouterModule模块
│  ├──src/main/ets/components/mainpage
│  │  ├──B1.ets
│  │  ├──B2.ets
│  │  └──B3.ets
│  └──src/main/resources
├──harC                                           // 子业务模块
│  ├──Index.ets                                   // 入口文件,对外暴露模块方法
│  ├──oh-package.json5                            // 依赖配置,需依赖RouterModule模块
│  ├──src/main/ets/components/mainpage
│  │  ├──C1.ets
│  │  └──C2.ets
│  └──src/main/resources
└──RouterModule                                   // 路由模块
   ├──Index.ets                                   // 入口文件,对外暴露路由的方法和常量
   ├──oh-package.json5
   ├──src/main/ets/constants                      // 路由信息常量
   │  └──RouterConstants.ets
   ├──src/main/ets/model                          // 路由信息模型
   │  └──RouterModel.ets
   ├──src/main/ets/utils                          // 对外提供的路由方法
   │  └──RouterModule.ets
   └──src/main/resources

具体实现

RouterModule模块

RouterModule
//RouterModule工具类


import { RouterModel } from '../model/RouterModel';
import Logger from './Logger';

export class RouterModule {
  //用来存放wrapbuilder 一个wrapbuilder对应一个navDestination
  static builderMap: Map<string, WrappedBuilder<[object]>> = new Map<string, WrappedBuilder<[object]>>();
  //用来存放路由栈的 一个Navigation会有一个NavPathStack 如果项目只需要一个Navigation不需要这一步
  static routerMap: Map<string, NavPathStack> = new Map<string, NavPathStack>();

  // 把一个navDestination存放在map里面
  public static registerBuilder(builderName: string, builder: WrappedBuilder<[object]>): void {
    RouterModule.builderMap.set(builderName, builder);
  }

  // 通过名字获取到对应的navDestination
  public static getBuilder(builderName: string): WrappedBuilder<[object]> {
    const builder = RouterModule.builderMap.get(builderName);
    if (!builder) {
      Logger.info('not found builder ' + builderName);
    }
    return builder as WrappedBuilder<[object]>;
  }

  // 把一个navpathstack存放在map里面
  public static createRouter(routerName: string, router: NavPathStack): void {
    RouterModule.routerMap.set(routerName, router);
  }

  //通过名字获取到对应的navpathstack
  public static getRouter(routerName: string): NavPathStack {
    return RouterModule.routerMap.get(routerName) as NavPathStack;
  }

  // 通过RouterModel跳到对应的NavDestination页面 (RouterMoudel会在下面讲)
  public static async push(router: RouterModel): Promise<void> {
    //切割出来har包名字 因为BuilderName我们的命名规则是'@ohos/hara_A1' 这样
    const harName = router.builderName.split('_')[0];
    // 不懂这里面为什么await加上.then 但是不这么写就会报错
    // 加载har名字 在对应har里面index设置动态加载页面组件的接口harInit,这边下面会有对应的代码
    await import(harName).then((ns: ESObject): Promise<void> => ns.harInit(router.builderName));
    // 通过获取的路由栈 进行push到相关的NavDestination里面
    RouterModule.getRouter(router.routerName).pushPath({ name: router.builderName, param: router.param });
  }

  // 返回到上一个页面 相当于router.back 
  public static pop(routerName: string): void {
    // Find the corresponding route stack for pop.
    RouterModule.getRouter(routerName).pop();
  }

  //清除页面栈
  public static clear(routerName: string): void {
    // Find the corresponding route stack for pop.
    RouterModule.getRouter(routerName).clear();
  }

  //返回到对应的NavDestination上
  public static popToName(routerName: string, builderName: string): void {
    RouterModule.getRouter(routerName).popToName(builderName);
  }
}
RouterModel
//RouterModel


import { RouterModule } from '../utils/RouterModule';

//一个NavDestination 一个对应的Navpathstack 一个传的参数
export class RouterModel {
  builderName: string = "";

  routerName: string = "";
  //传的param
  param?: object = new Object();
}

//把routermodel传到push里面 
export function buildRouterModel(routerName: string, builderName: string, param?: object) {
  let router: RouterModel = new RouterModel();
  router.builderName = builderName;
  router.routerName = routerName;
  router.param = param;
  RouterModule.push(router);
}
RouterConstants
//这个页面没什么东西 就是index对应的harinit
export class BuilderNameConstants {
   //我们在上面的RouterModule里面做了一个slice('_')[0]的操作 目的就是为了把har包的依赖名字切出来
  static readonly HARA_A1: string = '@ohos/hara_A1';
  static readonly HARA_A2: string = '@ohos/hara_A2';
  static readonly HARB_B1: string = '@ohos/harb_B1';
  static readonly HARB_B2: string = '@ohos/harb_B2';
  static readonly HARB_B3: string = '@ohos/harb_B3';
  static readonly HARC_C1: string = '@ohos/harc_C1';
  static readonly HARC_C2: string = '@ohos/harc_C2';
}


export class RouterNameConstants {
  static readonly ENTRY_HAP: string = 'EntryHap_Router';
}





// 这个是跳转到的har包需要配置的index 因为怕看不懂在这个代码块写
在子模块中添加动态加载页面组件的接口harInit,其中pageName和RouterInfo中配置的pageName相同,import()接口中传入的参数,是页面的相对路径。详细代码可参考Index.ets。 如果模块中有多个页面需要跳转,则需要配置多个pageName和页面路径,并且pageName和页面路径需要一一对应,否则无法跳转到预期中的页面
import { BuilderNameConstants } from '@ohos/routermodule';

export function harInit(builderName: string): void {
  // 动态引入要跳转的页面
  switch (builderName) {
    //通过对应的builderNmae跳转到对应的页面
    case BuilderNameConstants.HARA_A1:
      import("./src/main/ets/components/mainpage/A1");
      break;
    case BuilderNameConstants.HARA_A2:
      import("./src/main/ets/components/mainpage/A2");
      break;
    default:
      break;
  }
}

Entry模块

import { BuilderNameConstants, buildRouterModel, RouterModule, RouterNameConstants } from '@ohos/routermodule';

@Entry
@Component
struct EntryHap {
  @State entryHapRouter: NavPathStack = new NavPathStack();

  aboutToAppear() {
    if (!this.entryHapRouter) {
      this.entryHapRouter = new NavPathStack();
    }
    //初始化路由比哦啊哦
    RouterModule.createRouter(RouterNameConstants.ENTRY_HAP, this.entryHapRouter);
  };

  @Builder
  routerMap(builderName: string, param: object) {
   
    RouterModule.getBuilder(builderName).builder(param);
  };

  build() {
    Navigation(this.entryHapRouter) {
      Button($r("app.string.to_hara_pageA1"), { stateEffect: true, type: ButtonType.Capsule })
        .width('80%')
        .height(40)
        .margin(20)
        .onClick(() => {
         //这个方法里面有push,第一个参数的路由栈的名字 第二个参数的跳转的NavDestinatio的名字
          buildRouterModel(RouterNameConstants.ENTRY_HAP, BuilderNameConstants.HARA_A1, new Object({
            origin: 'Entry'
          }));
        })
    }
    .title('NavIndex')
    //创建NavDestination组件。使用builder函数,基于name和param构造NavDestination组件。builder下只能有一个根节点。builder中允许在NavDestination组件外包含一层自定义组件, 但自定义组件不允许设置属性和事件,否则仅显示空白。
    .navDestination(this.routerMap);
  }
}

HAR_A模块

import { BuilderNameConstants, buildRouterModel, RouterModule, RouterNameConstants, } from '@ohos/routermodule';

@Builder
export function harBuilder(value: object) {
  NavDestination() {
    Column() {
      Text(`传入的参数:${JSON.stringify(value)}`)
        .margin(20)
      Button($r("app.string.to_index"), { stateEffect: true, type: ButtonType.Capsule })
        .width('80%')
        .height(40)
        .margin(20)
        .onClick(() => {
          RouterModule.clear(RouterNameConstants.ENTRY_HAP);
        })
    }
    .width('100%')
    .height('100%')
  }
  .title('A1Page')
  .onBackPressed(() => {
    RouterModule.pop(RouterNameConstants.ENTRY_HAP);
    return true;
  })
}

const builderName = BuilderNameConstants.HARA_A1;
//如果map里面找不到对应的builder就把他存起来
if (!RouterModule.getBuilder(builderName)) {
   //把上面的全局builder存在wrapBuilder里面
  const builder: WrappedBuilder<[object]> = wrapBuilder(harBuilder);
  RouterModule.registerBuilder(builderName, builder);
}

这就实现了基本的动态路由

参考代码

applications_app_samples: We provide a series of app samples to help you quickly get familiar with the APIs and app development process of the OpenHarmony SDKs. | 为帮助开发者快速熟悉OpenHarmony SDK所提供的API和应用开发流程,我们提供了一系列的应用示例 - Gitee.com

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过使用 Vue Router 和动态路由来实现动态路由导航菜单。 首先,在 Vue Router 中定义动态路由。例如,我们可以定义一个名为 `Category` 的路由,并将其作为一个动态路由: ``` const router = new VueRouter({ routes: [ { path: '/category/:id', name: 'Category', component: Category } ] }) ``` 接下来,在组件中使用 `this.$router.push()` 方法来动态导航到路由。例如,我们可以在导航菜单组件中使用 `v-for` 循环来创建菜单项,并在点击菜单项时使用 `this.$router.push()` 来动态导航到相应的路由: ``` <template> <div> <ul> <li v-for="category in categories" :key="category.id" @click="navigate(category.id)"> {{ category.name }} </li> </ul> </div> </template> <script> export default { data() { return { categories: [ { id: 1, name: 'Category 1' }, { id: 2, name: 'Category 2' }, { id: 3, name: 'Category 3' } ] } }, methods: { navigate(id) { this.$router.push({ name: 'Category', params: { id: id } }) } } } </script> ``` 在上面的示例中,我们使用 `v-for` 循环创建菜单项,并在点击菜单项时调用 `navigate()` 方法来动态导航到相应的路由。在 `navigate()` 方法中,我们使用 `this.$router.push()` 方法来动态导航到名为 `Category` 的路由,并将路由参数 `id` 设置为当前菜单项的 `id` 值。 最后,在 App.vue 中包含导航菜单组件和路由出口: ``` <template> <div> <NavigationMenu /> <router-view /> </div> </template> <script> import NavigationMenu from './components/NavigationMenu.vue' export default { components: { NavigationMenu } } </script> ``` 以上就是实现 Vue 动态路由导航菜单的基本步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值