【鸿蒙实战开发】基于Navigation的路由管理

Navigation介绍

Navigation简介

  1. Navigation:路由导航的根视图容器,一般作为页面(@Entry)的根容器去使用,包括单页面(stack)、分栏(split)和自适应(auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果。一次开发,多端部署场景下,Navigation组件能够自动适配窗口显示大小,在窗口较大的场景下自动切换分栏展示效果。

  1. Title:标题栏,通过title属性对标题栏进行设置。通过menus配置菜单
  2. NavContent:内容区域,默认首页显示导航内容(Navigation的子组件)或非首页显示(NavDestination的子组件),首页和非首页通过路由进行切换。
  3. ToolBar:工具栏,通过toolbarConfiguration实现对工具栏的配置,如果不配置此属性,ToolBar不显示。竖屏最多支持显示5个图标,多余的图标会被放入自动生成的更多图标。
  4. NavDestination:作为子页面的根容器,用于显示Navigation的内容区。具备两种类型:STANDARD(标准类型,NavDestination的生命周期跟随NavPathStack栈中标准NavDestination变化而改变),DIALOG(默认透明。不影响其他NavDestination的生命周期)。
  5. NavPathStack:Navigation路由栈,由于管理NavDestination组件的路由跳转。推荐使用NavPathStack配合navDestination****属性进行页面路由。

Navigation路由页面生命周期简介

Navigation由NavDestination组件组成页面路由,在实现过程中NavDestination组件会被封装在一个自定义组件中,从而作为一个页面被路由栈使用。当前支持的生命周期函数:aboutToAppear、onReady、onAppear、onShow、onHide、onDisappear、aboutToDisappear 、onWillAppear、onWillDisappear

事件名称 描述
aboutToAppear 自定义组件析构销毁之前执行。
onAppear 组件挂载显示时触发此回调。
onReady 当NavDestination即将构建子组件之前会触发此回调。
onShown 当该NavDestination页面显示时触发此回调。
onHidden 当该NavDestination页面隐藏时触发此回调。
onDisAppear 组件卸载消失时触发此回调。
aboutToDisappear 在自定义组件析构销毁之前执行。

Navigation VS Router

当前HarmonyOS支持两套路由机制(Navigation和Router),Navigation作为后续长期演进及推荐的路由选择方案,其与Router比较的优势如下:

  • 易用性层面:
  1. Navigation天然具备标题、内容、回退按钮的功能联动,开发者可以直接使用此能力。Router若要实现此能力,需要自行定义;
  2. Navigation的页面是由组件构成,易于实现共享元素的转场。
  • 功能层面:
  1. Navigation天然支持一多,Router不支持;
  2. Navigation没有路由数量限制,Router限制32个;
  3. Navigation可以获取到路由栈NavPathStack,并对路由栈进行操作;
  4. Navigation可以嵌套在模态对话框中,也就是说可以模态框中定义路由,Router不支持;
  5. Navigation的组件全量由开发者自行控制,开发者可以自定义复杂的动效和属性的设置(背景、模糊等),Router的page对象不对外暴露,开发者无法对page进行处理。
  • 性能层面
  1. Navigation传递参数性能更优,Navigation通过引用传递,Router通过深拷贝完成;
  2. Navigation可以配合动态加载,实现组件动态加载,Router页面使用@Entry进行修饰,当前模块加载时会生成全量页面。

Navigation & Router****结构对比

  1. Navigation中的每个页面,承载在一个page里,通过NavDestination容器实现基于组件的页面跳转。
  2. Router的每一个页面配置在一个单独的page中,通过@Entry进行标识。

Navigation & Router****能力对比

业务场景 Navigation能力 Router能力
跳转指定页面 pushPath & pushDestination pushUrl & pushNameRouter
跳转HSP中页面 支持,需要先import页面 支持
跳转HAR中页面 支持,需要先import页面 支持
跳转传参 支持 支持
获取指定页面参数 支持 不支持
跳转结果回调 支持 支持
跳转单例页面 可通过判断栈内有没有此页面,调用moveToTop实现 支持
页面返回 pop back
页面返回传参 支持 支持
返回指定路由 popToName&popToIndex 不支持
页面返回弹窗 通过路由拦截实现 showAlertBeforeBackPage
路由替换 replacePath & replacePathByName replaceUrl & replaceNameRouter
路由栈清理 clear clear
清理指定路由 removeByIndexes & removeByName 不支持
转场动画 支持 支持
自定义转场动画 支持 支持
屏蔽转场动画 pushDestination(info: NavPathInfo, animated?: boolean) & patshStack.disableAnimation(true) 支持 duration属性设置为0
共享元素动画 支持 不支持
页面生命周期监听 UIObserver.on(‘navDestinationUpdate’) UIObserver.on(‘routerPageUpdate’)
获取页面栈对象 支持 不支持
路由拦截 setInterception 不支持
路由栈信息查询 getAllPathName & getParamByIndex & getParamByName&size getState() & getLength()
路由栈操作 moveToTop & moveIndexToTop 不支持
沉浸式页面 支持 不支持,需通过window配置
设置页面属性(背景,模糊等) 支持,backgroundBlurStyle 不支持
设置页面标题栏(title)和工具栏(toolbar) 支持 不支持
模态嵌套路由 支持 不支持

Navigation常见场景&解决方案

路由跳转场景

页面跳转是路由最常用的能力,Navigation通过NavPathStack提供了诸多方法,下文以pushDestination方法为例,介绍Navigation的路由跳转相关能力。

页面间跳转
NavPathStack提供了路由管理的能力,通过NavPathStack进行页面跳转,主要适用于页面较多的应用。

Step1:创建NavPathStack对象pageStack,通常使用@Provide进行修饰,方便后续子组件通过@Consumer获取,以实现子页面的路由跳转。也可以将pageStack传入路由框架,以实现路由框架开发(后续路由框架章节会介绍)的开发

@Entry

@Component

struct mainPageView {

  @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()

  ...

  build() {

    ...

  }

}

Step2:构建路由表pageMap,该方法通过@Builder进行修饰,通过传入的pageName属性,返回不同页面。

@Entry

@Component

struct mainPageView {

  @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()

  @Builder

  PageMap(pageName: string) {

    if (pageName === 'loginPage') {

      loginPageView()

    } else if (pageName === 'mainPage') {

      mainPageView()

    }

  }

  build() {

    ...

  }

}

Step3:在build创建Navigation组件(需要传入pageStack参数),通过navDestination属性传入路由表pageMap,并通过pageStack.pushPath()实现页面跳转。

@Entry

@Component

struct mainPageView {

  @Provide('pageStack') pageStack: NavPathStack = new NavPathStack()

  @Builder

  pageMap(pageName: string) {

    if (pageName === 'loginPage') {

      loginPageView()

    } else if (pageName === 'mainPage') {

      mainPageView()

    }

  }

  build() {

    Navigation(this.pageStack){

      ...

      Button('login').onClick( ent => {

        let pathInfo : NavPathInfo = new NavPathInfo('loginPage', null)

        this.pageStack.pushDestination(pathInfo, true);

      })

    }.navDestination(this.pageMap)

    ...

  }

}

页面间参数传递

Navigation的页面间,通过NavPathInfo对象中的params属性,实现从发起页到目标页的数据传递;通过onPop回调参数,实现处理目标页面的返回。

Step1:构建NavPathInfo对象,输入需要传递给目标页面的参数。params参数:将需要传递的数据封装起来进行传递。onPop参数:目标页面触发pop时的返回,在回调中通过PopInfo.info.param获取到返回的对象。

// 发起页 mainPage

let loginParam : LoginParam = new LoginParam()

// 构建pathInfo对象

let pathInfo : NavP
### 鸿蒙系统中 Navigation 路由拦截机制及其实现方法 鸿蒙系统的 `Navigation` 组件提供了强大的路由管理能力,其中包括路由拦截功能。这种功能允许开发者在用户导航至目标页面之前执行特定逻辑,例如验证用户的登录状态、权限检查或者显示提示框等。 #### 1. **核心概念** 路由拦截的核心在于通过 `setInterception` 或者自定义拦截器来实现对路由请求的控制。当用户尝试访问某个页面时,拦截器会先被触发,从而决定是否继续跳转或转向其他页面[^2]。 #### 2. **实现流程** ##### (1)创建拦截器 拦截器可以通过继承 `InterceptorExecute` 接口并重写其 `executeFunction` 方法来定制化拦截逻辑。以下是拦截器的一个典型实现: ```typescript // 定义拦截器类 export class MyPageInterceptorExecute implements InterceptorExecute { executeFunction(routerInfo: RouterInfo, param?: string): boolean { // 判断当前要跳转的目标页面名称 if (routerInfo !== undefined && routerInfo.pageName === "MyPage") { // 检查用户是否已登录 const isLoggedIn = AppStorage.get("isLoggedIn"); if (!isLoggedIn) { // 用户未登录,则跳转到登录页面 DynamticRouter.push("LoginPage", param); return true; // 返回true表示拦截成功,阻止原定跳转 } } // 对于其他页面或者已经登录的情况,放行 return false; } } ``` 此代码片段展示了如何根据目标页面名以及用户的登录状态来决定是否拦截跳转操作[^4]。 ##### (2)注册拦截器 完成拦截器编写后,需要将其注册到全局拦截器列表中以便生效: ```typescript // 注册拦截器 Interceptor.registerInterceptorPage(new MyPageInterceptorExecute()); ``` 这一步骤确保每次路由切换都会经过该拦截器的检测[^4]。 ##### (3)配置动态路由 如果项目中有多个可能需要拦截的路径,建议统一维护一份路由映射表,并结合动态路由技术灵活调整行为模式。例如,在某些特殊情况下临时启用或禁用某项拦截规则。 ```typescript const RouterInfo = { NAVIGATION_INTERCEPTOR: { pageName: 'MyPage' }, MULTI_MODAL_TRANSITION: { pageName: 'LoginPage' } }; ``` 以上代码用于定义不同页面对应的标识符,便于后续逻辑中的匹配过程更加清晰明了[^4]。 #### 3. **实际应用场景举例** - **登录校验**:如前所述,可以在用户试图打开受保护资源(如个人中心)前确认身份合法性。 - **权限审核**:针对部分高级功能模块实施细粒度授权策略,防止越权访问。 - **引导页展示**:首次启动应用时自动呈现新手指引界面而非默认首页。 #### 4. **注意事项** 为了提升用户体验,应尽量减少不必要的中断动作;同时也要注意性能开销问题——复杂的异步任务可能会延迟响应速度甚至引发卡顿现象。因此设计合理的缓存方案显得尤为重要[^3]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值