it编程 > 硬件开发 > arm开发

HarmonyOS开发 :Router 和 NavPatchStatck 如何实现跳转(传参)及页面回调

70人参与 2024-08-06 arm开发

路由的选择

harmonyos提供两种路由实现的方式,分别是 routernavpatchstack。两者使用场景和特效各有优劣。

组件适用场景特点备注
router模块间与模块内页面切换通过每个页面的url实现模块间解耦
navpathstack模块内页面切换通过组件级路由统一路由管理

如果是单包应用开发,不使用动态包(hsp)进行拆包,只是使用静态包(har)简单的进行模块拆分,那么我推荐使用 navpatchstack

如果像开发 鸿蒙元服务,对单包体积有 2m 的限制,那么我们不得不使用动态包的方式。将相对独立的功能,二级页面等拆分出去,封装成动态包,可避开 dependencies 直接依赖得引用形式。

此时使用 router 跳转 url 的方式才可跳转到动态包内非直接引用的页面

navpatchstatck 如何跳转(传参)及页面回调

navpathstack 是配合 navigation 一起使用的, navigation导航组件做统一的页面跳转管理,它提供了一系列属性方法来设置页面的标题栏、工具栏以及菜单栏的各种展示样式。

如何跳转(传参)及实现页面回调?

//第一步:定义一个用于传参和实现页面回调的模型
export interface routermodel {
  params?: object, // 要传递给跳转页面的参数
  popcallback?: (value: object | undefined) => void // 用于页面回调
}
//第二步,需要在应用的根页面自行维护 navstack 实例,并传递给根节点 navigation
@provide('navpathstack') navpathstack: navpathstack = new navpathstack()

navigation(this.pageinfos) {
  column() {}
}
.title('navindex')
.navdestination(this.pagemap)


// 统一管理维护路由跳转
@builder
  pagemap(name: string, params: routermodel) {
    if (name === 'pageone') {
      testnavpathpage({ // testnavpathpage 就是要跳转的目标页面
        routerparams: params
      })
    } else {
      // 默认空页面
    }
}

/// 任意一个页面获取 navpathstack 调用跳转并传参
@component
export struct routercallbackexample {
  @consume('navpathstack') navpathstack: navpathstack;
 

  // navpatchstack 方式跳转并获取回调
  navpathstackjump() {
    const routerparams: routermodel = {
      params: '我是入参 123', //传递到跳转页面的入参
      popcallback: (callbackvalue) => {
        // 这里拿到回调结果,注意要判断 callbackvalue !== undefine
        // 这里拿到下面目标页面回传的结果 ‘我是回调的结果 345’
      }
    }
   this.navpathstack.pushpathbyname('pageone', routerparams) // 'pageone' 对应上面 'pagemap' 方法内定义的路径名称常量
  }

  build() {
    button('跳转').onclick(() => {
        this.navpathstackjump()
    })
  }
}

/// 目标页面接收入参、并返回页面回调
@component
export struct testnavpathpage {
  @consume('navpathstack') navpathstack: navpathstack;
  routerparams?: routermodel
  @state receiveparams: string = ''

  abouttoappear(): void {
    // 接收入参,这里拿到上面传入的 ‘我是入参 123’
    let receiveparams = this.routerparams!.params
  }

  build() {
    navdestination() {
      button('关闭页面并回调结果').onclick(() => {
        if (this.routerparams?.popcallback !== undefined) {
          this.routerparams.popcallback('我是回调的结果 345 ')
        }
        this.navpathstack.pop()
      })
    }.title('跳转目标页')
  }
}

router 如何跳转(传参)及页面回调

router 跳转可支持跳转本包内页面以及动态包或者拆包内的页面,

1. 本地包内,或者直接依赖的静态包内页面,url 定义为 : pages/page1
2. 分包内的页面,url 定义为 :@bundle:com.rex.harmony.atomic.service/featurename/ets/pages/page2

// com.rex.harmony.atomic.service 是我的应用包名
// featurename 是跳转页面所在的模块名称,对应 module.json5 里面额 name
// ets/pages/page2 为目标页面在模块内的页面路径,对应 main_pages.json 内的页面路径
router.pushurl({ url: '', params: object })

  1. 在公共的har包内定义 router 管理类 fastrouter

(在下文扩展中解释单例为什么这么实现)

import { routermodel } from './model/routermodel'
import { router } from '@kit.arkui'

/// 基于 router 库封装,为了实现页面回调
export class fastrouter {
  public readonly routerstack: routermodel[] = []

  /// 跨 hsp 使用这种方式实现单例
  public static instance(): fastrouter {
    const storagekey = 'rex_fast_router'
    if (!appstorage.has(storagekey)) {
      appstorage.setorcreate(storagekey, new fastrouter())
    }
    return appstorage.get<fastrouter>(storagekey)!
  }

  /// 获取路由传递的入参
  public static get getroutercurrentparams(): routermodel | undefined {
    const stack = fastrouter.instance().routerstack
    if (stack.length === 0) {
      return undefined
    }
    return stack[stack.length - 1]
  }

  /// push 页面
  public static async push(route: routermodel): promise<void> {
    try {
      await router.pushurl({ url: route.url, params: route.params })
      fastrouter.instance().routerstack.push(route)
    } catch (_) {
      console.log('>>>>')
    }
  }

  /// replace 页面
  public static async replace(route: routermodel): promise<void> {
    try {
      await router.replaceurl({ url: route.url, params: route.params })
      const instance = fastrouter.instance()
      const list = instance.routerstack
      if (list.length > 0) {
        instance.routerstack.splice(instance.routerstack.length - 1, 1, route)
      }
    } catch (_) {
      // 暂无处理
    }
  }

  /// 退出栈顶页面
  public static async pop(animated?: boolean): promise<void> {
    router.back()
    const routerstack = fastrouter.instance().routerstack
    routerstack.pop()
  }
}
  1. 任一页面使用 fastrouter 进行 url 跳转
// 跳转到 hsp 包(feature_hsp_page)内的 testhsphomepage 页面
const routerparams: routermodel = {
  url: '@bundle:com.rex.harmony.atomic.service/feature_hsp_page/ets/pages/testhsphomepage',
  params: '我是入参 1488',
  popcallback: (callbackvalue) => {
    if (callbackvalue !== undefined) {
      //这里获取跳转页的回调数据
      //接收到下文中目标页面的回调结果:‘我是回调的结果 6100 ’
    }
  }
}
fastrouter.push(routerparams)
  1. 在目标页面内接收入参并回调结果
@entry
@component
struct index {
  routerparams?: routermodel

  abouttoappear(): void {
    this.routerparams = fastrouter.getroutercurrentparams as routermodel
    let receiveparams = this.routerparams.params //这里接收入参,也就是上面传递的 ‘我是入参 1488’
  }

  build() {
    button('关闭页面并回调结果').onclick(() => {
      if (this.routerparams?.popcallback !== undefined) {
        this.routerparams.popcallback('我是回调的结果 6100 ')
      }
      fastrouter.pop()
    })
  }
}

总结

navpatchstackrouter 两种路由方式各有优劣,navpatchstack 方便统一管理,router 方便解耦,两者没有任何关联,可以一起使用,也可以单独使用。

扩展:动态包、静态包的使用差异

说到动态包(har)和静态包(hsp),这里扩展一下两者的区别。

静态包的 module.json5 文件,type 标识为 har

{
  "module": {
    "name": "静态包模块名称",
    "type": "har",
    "devicetypes": [
      "default",
      "tablet"
    ]
  }
}

静态包的 module.json5 文件,type 标识为 shared

{
  "module": {
    "name": "动态包模块名称",
    "type": "shared",
    "description": "$string:shared_desc",
    "devicetypes": [
      "phone",
      "tablet"
    ],
    "deliverywithinstall": true,
    "installationfree": true,
    "pages": "$profile:main_pages"
  }
}

动态包和静态包都可以被直接引用,在 oh-package.json5

{
 ...省略
  "dependencies": {
    "@rex/任意名称": "file:../../base/静态包模块名称",
    "@rex/任意名称": "file:../../base/动态包模块名称"
  }
}

重点:

举个例子:

    class simgleprovider {
      private static _instance?: simgleprovider

      public static instance(): simgleprovider {
        if (!simgleprovider._instance) {
          simgleprovider._instance = new simgleprovider()
        }
        return simgleprovider._instance
      }
    }
class simgleprovider {
  private static _instance?: simgleprovider

  public static instance(): fastrouter {
    const storagekey = 'simgleprovider'
    if (!appstorage.has(storagekey)) {
      appstorage.setorcreate(storagekey, new simgleprovider())
    }
    return appstorage.get<simgleprovider>(storagekey)!
  }
}


最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(harmonyos next)资料用来跟着学习是非常有必要的。 

鸿蒙harmonyos next全套学习资料←点击领取!(安全链接,放心点击

这份鸿蒙(harmonyos next)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(arkts、arkui开发组件、stage模型、多端部署、分布式应用开发、音频、视频、webgl、openharmony多媒体技术、napi组件、openharmony内核、harmony南向开发、鸿蒙项目实战等等)鸿蒙(harmonyos next)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

鸿蒙(harmonyos next)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(openharmony )学习手册(共计1236页)与鸿蒙(openharmony )开发入门教学视频,内容包含:arkts、arkui、web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙harmonyos学习资料

harmonyos next 最新全套视频教程

《鸿蒙 (openharmony)开发基础到实战手册》

openharmony北向、南向开发环境搭建

《鸿蒙开发基础》

《鸿蒙开发进阶》

《鸿蒙进阶实战》

大厂面试必问面试题

鸿蒙南向开发技术

鸿蒙app开发必备

鸿蒙生态应用开发白皮书v2.0pdf


获取以上完整鸿蒙harmonyos学习资料,请点击→

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

【愚公系列】2023年12月 HarmonyOS应用开发者基础认证(完美答案)

08-06

DevEco Studio No device 无法识别 usb 设备 - 鸿蒙

08-06

HarmonyOS Next 纯血星河版【六】【ArkTS语法】:数组的增删改查操作、判断和循环以及算元语句、条件渲染(淘宝购物车案例)、数组的遍历和数组对象的定义使用、ForEach遍历渲染的使用

08-06

线性模型:AR、MA、ARMA、ARMAX、ARX、ARARMAX、OE、BJ等

08-06

PyCharm部分实用快捷键和插件

08-06

pycharm手动安装常用插件

08-06

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论