广州网站建设粤icp,网站建设需要精通什么知识,免费手机网站制作方法,徐州模板网站托管平台本文为JS老狗原创。
当前端不得不关注的点#xff1a;路由#xff0c;今天聊一聊鸿蒙相关的一点心得。
总体上套路不意外#xff0c;基本就是#xff08;尤其是Web#xff09;前端那些事#xff1a;维护路由表、跳转带参数、历史堆栈操作#xff0c;等等。
历史原因路由今天聊一聊鸿蒙相关的一点心得。
总体上套路不意外基本就是尤其是Web前端那些事维护路由表、跳转带参数、历史堆栈操作等等。
历史原因ArkTS提供了两套方案router和Navigation。我厂进入比较早还是采用的router方案Navigation的方案只是个人大致研究了一下。下面分别聊一聊。
使用ohos.router
通过路由地址跳转
当我们以下图的路径创建页面时开发工具会自动记录一个页面路由 文件路径src/main/resources/base/profile/main_pages.json 在同一module中我们可以使用ohos.router库快速实现页面跳转
import router from ohos.router;Entry
Component
struct Index {build() {Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Button(Page1).onClick(() {router.pushUrl({ url: pages/Page1 })})}.width(100%).height(100%)}
}效果如下 这个操作过程跟小程序的创建页面和自动记录路由的过程非常类似跳转过程跟各路router也差不多。
当然我们也可手动创建文件以及手工维护这个路由表。
通过路由命名跳转
我们可以在Entry装饰器上对页面进行路由命名
Entry({ routeName: Page2 })
Component
struct Page2 {State message: string Page2;build() {RelativeContainer() {Text(this.message).id(Page2HelloWorld).fontSize(50).fontWeight(FontWeight.Bold).alignRules({center: { anchor: __container__, align: VerticalAlign.Center },middle: { anchor: __container__, align: HorizontalAlign.Center }})}.height(100%).width(100%)}
}然后在索引页面上import这个页面通知注册路由名称
import router from ohos.router;
import ./Page2
// ...这里只是为了注册routeName需要代码层import一个页面并不是很优雅。
另外还有一种import(./Page2.ets)的方式意思差不多只是这里算动态引用。我们在某些windows模拟器上发现只能使用这种动态引用复现不稳定如有问题可试试这种方式。
新增一个按钮使用router.pushNamedRoute向Page2跳转
Button(Page2).onClick(() {router.pushNamedRoute({ name: Page2 })
})看下效果 由于路由表是维护在module内的所以当时项目使用多module时使用routeName跳转会比较方便。唯一的缺点就是需要额外import页面。
参数传递
跳转时代入params用于传递参数
router.pushUrl({ url: pages/Page1, params: { productId: 123 } })在目标页使用router.getParams()获取参数
import router from ohos.router;Entry
Component
struct Page1 {State message: string Page1;State productId: string onPageShow(): void {const params (router.getParams() || {}) as Recordstring, Objectthis.productId ${params.productId || }}build() {// ...}
}请注意router.getParams()又可能返回null取值请注意降级。
另外上面例子是在onPageShow阶段获取如果是从其他页面back回来的这种方式有可能会导致页面参数取值错误。
使用NavPathStackNavigation
其中NavPathStack是路由堆栈Navigation是UI组件可以快捷实现页头、底部tabBar等功能能。两者必须结合使用。
构建索引页
我们把Index页面重构一下
import router from ohos.router;
import ./Page2Entry
Component
struct Index {routeStack new NavPathStack()build() {Navigation(this.routeStack) {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Button(Page1).onClick(() {router.pushUrl({ url: pages/Page1 })}).margin({ bottom: 10 })Button(Page2).onClick(() {router.pushNamedRoute({ name: Page2 })}).margin({ bottom: 10 })}.width(100%).height(100%)}}
}由于我们未对Navigation组件做任何配置所以现在页面看不出变化。
维护路由表
这个过程可以简单分3步请依次完成。首先打开冰箱……
1、创建Page3仅用Component装饰使用Page3构建一个Builder声明为Page3Builder并导出
Builder
export function Page3Builder() {Page3()
}Component
struct Page3 {State message: string Page3;build() {RelativeContainer() {Text(this.message)//...}.height(100%).width(100%)}
}2、在目录src/main/resources/base/profile中创建文件route_map.json指向上面的Page3命名为page3。
这里的命名建议不要区分大小写比如驼峰什么的就算了全小写数字下划线不容易出错。
{routerMap: [{name: page3,pageSourceFile: src/main/ets/pages/Page3.ets,buildFunction: Page3Builder}]
}3、将路由表在module.json5中注册
{module: {// ...routerMap: $profile:route_map// ...}
}4、没想到吧其实这一步最重要了使用NavDestination包裹Page3否则跳过去也是白屏。
Builder
export function Page3Builder() {Page3()
}Component
struct Page3 {State message: string Page3;build() {NavDestination() {RelativeContainer() {Text(this.message).id(Page3HelloWorld).fontSize(50).fontWeight(FontWeight.Bold).alignRules({center: { anchor: __container__, align: VerticalAlign.Center },middle: { anchor: __container__, align: HorizontalAlign.Center }})}.height(100%).width(100%)}}
}5、对其实还有一步在索引页中发起跳转
Button(Page3).onClick(() {this.routeStack.pushPath({ name: page3 })
}).margin({ bottom: 10 })注意这里的跳转名应当严格一致。
看下效果 当然你一定发现了Page3的左上角有个返回按钮这就是NavDestination的效果之一。Navigation相关的路由跳转现在是官方的推荐做法。
参数传递 哎令人无奈。两个槽点
哪里冒出来的unknown类型router的参数名是params怎么这里又成了param
改造Page3
Builder
export function Page3Builder(name: string, param: Object) {Page3({ param })
}Component
struct Page3 {State message: string Page3;State product: string param: Object {} as Recordstring, Objectbuild() {NavDestination() {RelativeContainer() {Text(${this.message} - ${Reflect.get(this.param, product) || })//...}.height(100%).width(100%)}}
}请注意Page3Builder的参数传递以及在Page3构建时传入的参数。
另外也可在NavDestination.onReady周期获取上下文从上下文中拿到参数
build() {NavDestination() {// 。。。}.onReady(context {this.product Reflect.get(context.pathInfo.param, product)})
}别问Reflect.get是啥用就是了。
Navigation的UI配置
Navigation的UI配置非常丰富可以看出这个组件在开发时对各路路由UI都做了充分的调研用起来让人觉得简单得有点不敢相信。
构建页头
最简单的给页头起个名字并设置页头大小。
Entry
Component
struct Index {routeStack new NavPathStack()build() {Navigation(this.routeStack) {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {// ...}.width(100%).height(100%).backgroundColor(#fff)}.title(首页).titleMode(NavigationTitleMode.Mini).backgroundColor(#f1f1f1)}
}看下效果 这里titleMode的枚举值有
NavigationTitleMode.Mini NavigationTitleMode.Full / NavigationTitleMode.Free 自定义UI的页头
在页面中写个Builder
Builder
NavBar() {Flex({direction: FlexDirection.Column,justifyContent: FlexAlign.Center,alignItems: ItemAlign.Center,}) {Text(首页).fontSize(16)}.width(100%).height(100%).position({ x: 0 }).zIndex(-1)
}在build()中输入这个自定义页头
build() {Navigation(this.routeStack) {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {Button(Page1).onClick(() {router.pushUrl({ url: pages/Page1 })}).margin({ bottom: 10 })Button(Page2).onClick(() {router.pushNamedRoute({ name: Page2 })}).margin({ bottom: 10 })Button(Page3).onClick(() {this.routeStack.pushPath({ name: page3 })}).margin({ bottom: 10 })}.width(100%).height(100%).backgroundColor(#fff)}.title(this.NavBar) // ------- 看这里.titleMode(NavigationTitleMode.Mini).backgroundColor(#f1f1f1)
}请注意NavBar中用了一个zIndex(-1)这样就不会遮挡返回按钮了。
底部TabBar配置
先看下效果 toolbarConfiguration
build() {Navigation(this.routeStack) {// ...}.title(this.NavBar).titleMode(NavigationTitleMode.Mini).backgroundColor(#f1f1f1).toolbarConfiguration([{icon: https://res.suning.cn/project/cmsWeb/suning/homepage/v8/css/images/tool-logo.png,value: 首页,action: () {router.pushUrl({ url: pages/Page1 })}},{icon: https://image.suning.cn/uimg/cms/img/157105762930982264.png,value: 购物车,action: () {this.routeStack.pushPath({ name: page3 })}},{icon: https://image.suning.cn/uimg/cms/img/157105768303272975.png,value: 我的,action: () {router.pushNamedRoute({ name: Page2 })}}])
}简简单单配置icon/value/action即出成品。
写在最后
这个阶段对路由的研究大致就是如此。感觉像Navigation在UI方面的表现应该还有不少可以深挖的地方。
前面也有大佬们提过ArkTS跟Flutter像以及模式、架构跟mvvm也有相近之处到了路由这部分其实跟rn也有些相似了。
作为后来者相信ArkTS能够吸取众家之长成为集大成者。
关于OpenTiny
欢迎加入 OpenTiny 开源社区。添加微信小助手opentiny-official 一起参与交流前端技术 OpenTiny 官网https://opentiny.design/ TinyVue 源码https://github.com/opentiny/tiny-vue TinyEngine 源码 https://github.com/opentiny/tiny-engine OpenTiny HUICharts 源码https://github.com/opentiny/tiny-charts 欢迎进入代码仓库 StarTinyEngine、TinyVue、TinyNG、TinyCLI~ 如果你也想要共建可以进入代码仓库找到 good first issue标签一起参与开源贡献~
温馨提示OpenTiny CCF开源创新大赛也在持续报名中欢迎大家一起报名参赛赢取10W奖金