今天继续来学点鸿蒙相关的知识,本次内容讲的是页面路由,也就是我们熟悉的页面之间跳转传参等一系列操作,鸿蒙里面主要使用Router模块来完成这些页面路由相关操作,下面来详细介绍下
页面跳转
router.pushUrl()和router.replaceUrl()
这两个函数都可以用来页面跳转,区别在于
- router.pushUrl() :就像字面意思那样,会将一个新的页面推到页面栈的顶部,而旧页面依然存在,如果按下返回键或者调用
router.back()
,旧页面会回到栈顶. - router.replaceUrl() :也像字面意思那样,会把当前旧页面用新页面来代替,旧页面会被销毁,如果按下返回键或者调用
router.back()
,不会回到旧页面.
知道了概念后来写俩例子实践下,首先是第一个页面文件,命名它为FirstPage.ets
,所对应的路径是pages/FirstPage
,里面的代码是这样的
页面结构很简单,就是一个文案加一个按钮,按钮点击事件就是跳转至SecondPage
页面,我们看到这里的跳转方式是使用的pushUrl
方式,也就是把SecondPage
页面覆盖在FirstPage
上,SecondPage
里面的代码与FirstPage
基本相似,我们看下
也是一个按钮加一个文案,按钮的事件是调用router.back()
执行返回操作,这样一个完整的页面跳转加返回的操作就写完了,实际效果如下
实际效果也证实了,使用pushUrl
方式跳转,新页面会被加在页面栈顶端,而旧页面不会销毁,那么replaceUrl
又是怎么样的呢?我们将代码更改下
第一个页面里面,将跳转的方式改了一下,改成replaceUrl
,现在再看看效果
可以发现跳转到第二个页面之后,再点击返回已经回不到第一个页面了,那是因为第一个页面已经从栈里面销毁了
RouterMode
页面跳转分为两种模式,分别是RouterMode.Standard
和RouterMode.Single
,前者为跳转的默认模式,可不写,表示每次都新建一个页面实例,后者则表示单例模式,如果栈里面已经存在该页面实例,在启动它的时候会直接从栈里面回到栈顶,同样下面用代码来解释下这两种模式的区别,这里再新增一个页面ThirdPage
这个页面里面也有一个文案,另外还有两个按钮,返回按钮执行回退操作,跳转按钮则是跳转至SecondPage
,这里跳转的方式是用的pushUrl
,模式是Standard
,另外我们在SecondPage
里面也加一个跳转按钮,点击跳转至ThirdPage
,方式也是pushUrl
和Standard
代码都写完了,目前这样的跳转逻辑等于是如果我不停的在新页面里面点击跳转按钮,那就会一直新建页面,如果在某一个页面点击返回并一直点下去,会将之前创建好的页面一个不差的都经过一遍,最终才能回到第一个页面,我们看下实际效果
可以看到事实跟刚才讲的一样,但是很明显,将已经存在的实例重复创建是一件很消耗内存的事情,所以在这种需要再一次打开栈里面已经存在的实例的场景中,我们还是比较推荐使用Single
模式,我们将上述代码中跳转SecondPage
与ThirdPage
的模式改成Single
再试一次
我们看见仍旧是无限跳转下去,最终停在了SecondPage
上,但是如果从SecondPage
里面开始点击返回,还会不会原路返回呢,我们看下
我们看到,先返回到了ThirdPage
,然后TirdPage
点击返回直接回到了第一个页面,那是因为Single
模式下,SecondPage
与ThirdPage
是在不停的做着从栈内回到栈顶的操作,所以当点击返回时,第一个页面上面始终只覆盖了两个页面
页面传参
有些场景下除了页面需要跳转,另外还需要将当前页面的数据传递到新页面里面去,如何传递呢?可以先看下pushUrl
里面第一个参数RouterOption
里面都有哪些属性
第一个参数url
已经不用说了,都用过了,第二个参数params
就是页面跳转中携带的参数,可以看到是一个Object
,所以如果我们想传一个字符串到下一个页面,就不能直接将一个string
给到params
,得这样做
在params
里面以一个key-value形式传递参数,而在新页面里面,通过传递过来的key
把对应值取出来,我们在下一个页面获取参数的代码是这样写的
首先通过router.getParams()
将参数对象取出来,然后访问对应key
值就能将传递过来的数据取出来了,在SecondPage
里面还多增加了一个Text
组件用来显示传递过来的数据,最终运行下代码后看看数据有没有传过去
可以看到数据已经传过去了,但这里的场景比较简单,有的复杂的场景需要传递的数据不仅仅只有一个,会以一个model
的形式作为参数传递,那么遇到这样的场景该怎么做呢?
我们看到直接传递了一个UserModel
对象,而UserModel
就是我们封装的一个数据类,基本在实际开发中类似于UserModel
这样的数据就是一个接口的Response
,我们传递参数时候,只需将Response
传递过去就好了,而接收参数的地方的代码如下
可以发现,从页面跳转以及传参的这部分代码上,基本就与TypeScript的方式很相似了,看下实际效果
页面返回
说过了页面的跳转,那么跳完之后的返回操作也要说下,其实在上面的例子中,我们已经使用到了页面返回的函数,也就是router.back()
,这是其中一种返回方式,它总共有三种返回方式,分别如下
返回到上一个页面
使用router.back()
方式,如果当前页面是栈中唯一页面,返回将无效
返回到指定页面
可以通过传递一个url
返回到指定页面,如果该页面不在页面栈中,返回将无效,如果返回页与指定页面之间存在若干页面,那么指定页面被推到栈顶,返回页与中间的若干页面会被销毁,我们现在在之前的ThirdPage
中的返回按钮中加入如下代码
前面所有跳转方式都改为Standard
模式,在第三个页面中点击返回的时候,原来是直接退到第二个页面,现在指定了路径以后,我们看下调到哪里去了
直接回到第一个页面了,其他两个页面已经被销毁
返回并传递参数
有些场景需要在指定页面点击返回后,将一些数据从指定页面传递到返回后的页面,这种数据传递方式与跳转时候传递方式基本一致,因为back
函数中接收的参数也是RouterOptions
,比如现在从第一个页面跳到第二个页面再跳到第三个页面后,第三个页面点击返回跳到第一个页面,并且传递一些参数在第一个页面展示,代码如下
第一个页面中接收参数我们也在onPageShow()
里面进行
运行效果如下
返回时添加询问弹窗
这个操作主要是在一些重要页面里面,比如支付页面,或者一些信息填写页面里面,用户在未保存或者提交当前页面的信息时就点击了返回按钮,页面中会弹出个询问框来让用户二次确认是否要进行返回操作,这个询问框可以是系统弹框,也可以是自定义弹框
系统弹框
系统弹框可以使用router.showAlertBeforeBackPage
去实现,这个函数里面接收的参数为EnableAlertOptions
,这个类里面只有一个message
属性,用来在弹框上显示文案
使用方式如下,在router.back()
操作之前,调用一下router.showAlertBeforeBackPage
,弹框上会有确定和取消两个按钮,点击取消关闭弹窗停留在当前页面,点击确定就执行router.back()
操作
我们在ThirdPage
里面的返回操作中加入了系统询问框,可以看到我们要做的只是需要确定下弹框的文案就好,看下效果
但是如果我们想要更改下按钮文案,或者顺序,或者自定义按钮的点击事件,就不能用系统弹框了,得使用自定义询问框
自定义询问框
自定义询问框使用promptAction.showDialog
,在showDialog
里面接收的参数为showDialogOptions
,可以看下这个类里面有哪些属性
可以看到比系统弹框那边多了两个属性,能够设置弹框标题的title
以及按钮buttons
,可以看到buttons
是一个Button
的数组,最多可以设置三个按钮,注意这个Button
并不是我们熟悉的Button
组件,它内部只支持自定义文案以及颜色
知道了这些属性之后,我们可以把上面额系统询问框替换成这个自定义的询问框了,代码如下
可以看到弹框上面就多了一个标题,以及按钮的文案与颜色也变了,那么如何设置点击事件呢,现在两个按钮点了除了关闭按钮之外是没有别的操作的,如果想要添加其他操作,就需要通过then
操作符进行,在then
里面会拿到一个ShowDialogSuccessResponse
,这个类里面只有一个index
属性,这个index
就表示按钮的下标,可以通过判断下标来给指定按钮添加事件,代码如下
现在按钮点击后已经可以响应我们添加进去的事件了
总结
鸿蒙页面路由的所有内容都已经讲完了,总体感受比Android原生跳转要方便很多,完全就是按照TS的跳转方式写的,再一次证明了如果有声明式语言开发经验的,去学鸿蒙会相对轻松很多