浅谈 OpenHarmony 中北向应用实现页面跳转的几种方式
本文将介绍 OpenHarmony 中北向应用实现页面跳转的几种方式,涵盖了目前 (OpenHarmony v3.2) 常见的所有方法,开发者可以根据场景需求自行选择。
OpenHarmony 迭代迅速,版本间差异巨大。实际开发时,请确认设备的支持能力以及官方最新文档。
页面路由
@ohos.router
(页面路由) 本模块从 API Version 8 开始支持。
@system.router
(页面路由) 自 API Version 8 开始,该接口不再维护,推荐使用新接口 @ohos.router
。
这种方式只适用于在单一 Ability 内部的页面间跳转,不支持跨 Ability。
但这种方式的使用场景十分常见,例如点击查看详情 (router.push
) 并返回 (router.back
)。
导入模块
import router from '@ohos.router'
@ohos.router
模块中最常用的就是 router.push
、router.back
和 router.getParams
。
router.push
用于跳转到应用内的指定页面。router.back
返回上一页面或指定的页面。router.getParams
获取发起跳转的页面往当前页传入的参数。
除此之外,某些情况下也会使用 router.clear
。(清空页面栈中的所有历史页面,仅保留当前页面作为栈顶页面)
完整示例请见 GitHub 仓库,如果文章对您有所帮助的话,不妨点个 Star 再走。
// MainAbility Index Page
import router from '@ohos.router';
async routePage(url: string, params = {}) {
let options = {
url: url,
params: params
}
try {
await router.push(options)
} catch (err) {
console.info(`Fail in routePage(), code: ${err.code}, msg: ${err.msg}`)
}
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
......
.onClick(() => this.routePage('pages/param', { data: `Route From ${this.abilityName} ${this.pageName}` }))
······
}
// MainAbility Param Page
import router from '@ohos.router';
......
@Entry
@Component
struct Index {
@State data: number | string = router.getParams()['data']
......
.onClick(() => router.back())
······
}
若你使用 DevEco Studio 进行开发(大概没有人不用),请在侧边栏中右键选择 New
⇨ Page
新建页面。通过这种方式,DevEco Studio 将自动配置好 config.json
。
若你选择手动创建新页面,请参考 应用包结构说明(FA 模型)和应用包结构说明(Stage 模型)自行配置 config.json
文件。
router.push
和 router.back
接受的参数格式都为 RouterOptions
。
url
为目标页面的绝对路径,其中若该值为"/"
,则跳转到首页。params
为跳转时要同时传递到目标页面的数据,目标页面可通过router.getParams
获取发起跳转的页面往当前页传入的参数。
FeatureAbility 模块
在旧的 FA 模型中,使用 @ohos.ability.featureAbility
模块。
在新的 Stage 模型中,使用 @ohos.application.Ability
模块。
这种方式只适用于在不同 Ability 间跳转。
导入模块
import featureAbility from '@ohos.ability.featureAbility'
该模块提供了丰富的能力,包括启动新的 Ability、获取 dataAbilityHelper、设置此 Page Ability、获取当前 Ability 对应的窗口,连接服务等。
这里,我们只会用到 featureAbility.startAbility
和 featureAbility.getWant
。
featureAbility.startAbility
用于启动新的 Ability。featureAbility.getWant
用于获取从 Ability 发送的 Want。
除此之外,featureAbility.terminateSelf
和 featureAbility.terminateSelfWithResult
也是十分实用的 API。
完整示例请见 GitHub 仓库,如果文章对您有所帮助的话,不妨点个 Star 再走。
// MainAbility Index Page
import featureAbility from '@ohos.ability.featureAbility';
async startAbility(bundleName: string, abilityName: string, parameters = {}) {
let want = {
bundleName: bundleName,
abilityName: abilityName,
parameters: parameters
}
try {
await featureAbility.startAbility({ want: want });
} catch (err) {
console.info(`Fail in startAbility(), code: ${err.code}, msg: ${err.msg}`)
}
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
......
.onClick(() => this.startAbility('com.github.hydrotho.router', 'com.example.entry.SecondAbility', { url: 'pages/second', isPassingData: true }))
······
}
// SecondAbility Second Page
import featureAbility from '@ohos.ability.featureAbility';
async startAbility(bundleName: string, abilityName: string, parameters = {}) {
let want = {
bundleName: bundleName,
abilityName: abilityName,
parameters: parameters
}
try {
await featureAbility.startAbility({ want: want });
} catch (err) {
console.info(`Fail in startAbility(), code: ${err.code}, msg: ${err.msg}`)
}
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
@State isPassingData: boolean = false
......
async getWant() {
let want = await featureAbility.getWant()
if (!want) {
return
}
if (want.parameters.isPassingData === true) {
this.isPassingData = want.parameters.isPassingData
}
}
aboutToAppear() {
this.getWant()
}
······
.onClick(() => this.startAbility('com.github.hydrotho.router', 'com.example.entry.MainAbility'))
······
}
若你使用 DevEco Studio 进行开发(大概没有人不用),请在侧边栏右键菜单中新建 Ability
和 Page
。通过这种方式,DevEco Studio 将自动配置好 config.json
。
若你选择手动创建新页面,请参考 应用包结构说明(FA 模型)和应用包结构说明(Stage 模型)自行配置 config.json
文件。
这种方法使用时的关键在于 featureAbility.startAbility
接受的 Want
类型参数。
bundleName
其实就是config.json
中app
里的bundleName
属性所对应的值,也就是新建北向应用工程时输入的 Bundle Name。abilityName
值的构成为package
+ Ability Name。package
为config.json
中module
里的package
属性所对应的值。parameters
由开发者自行决定传入的键值对,例如目标页面不为其所在的 Ability 的默认页面时,传入url
指定目标页面。默认会携带以下键值:ohos.aafwk.callerPid
表示拉起方的 pid。ohos.aafwk.param.callerToken
表示拉起方的 token。ohos.aafwk.param.callerUid
表示发起方的 uid。
在许多网络上的教程以及官方文档中,bundleName
与 package
的值相同,导致人们误解以为 abilityName
的前缀为 bundleName
实际上并不是如此。
例如官方开发指导文档中的这段代码
import featureAbility from '@ohos.ability.featureAbility';
let promise = featureAbility.startAbility (
{
want:
{
bundleName: "com.jstest.service",
abilityName: "com.jstest.service.ServiceAbility",
},
}
);
看似 bundleName
与 abilityName
的前缀相同,其实只不过是这里 bundleName
与 package
的值相同。
初学者如果理不清这些概念,待到实际开发时,这就是个大坑。
在 @ohos.router
模块中,我们直接使用 RouterOptions
类型里的 url
属性指定目标页面。
而在 @ohos.ability.featureAbility
模块中,Want
类型里也有到看似类似的属性 uri
。初学者容易想当然地使用 uri
指定目标 Ability 的目标页面,这是不对的。实际上我们需要将目标页面地址包裹在 parameters
属性中,键名为 url
。
若进行页面跳转时携带了数据,目标页面可以在页面生命周期的早期调用 featureAbility.getWant()
获取源页面跳转时所传递的数据。
关于页面的生命周期,OpenHarmony 中 JS 语言和 eTS 语言有所不同,请参考 JS 语言页面生命周期函数和 eTS 语言页面生命周期函数。
例如,可以在 eTS 语言中的 aboutToAppear
生命周期函数中调用 featureAbility.getWant()
在页面显示前获取传递的数据,对页面进行调整。
WantAgent 模块
这种方式只适用于在不同 Ability 间跳转。
导入模块
import WantAgent from '@ohos.wantAgent';
WantAgent 模块提供了触发、取消、比较 WantAgent 实例等能力。
WantAgent 不仅可以开启 Ability,还可以发送公共事件,其行为可以通过 OperationType 操控。这里我们只使用 START_ABILITY
。
完整示例请见 GitHub 仓库,如果文章对您有所帮助的话,不妨点个 Star 再走。
// MainAbility Index Page
import wantAgent from '@ohos.wantAgent';
startAbilityViaWantAgent(bundleName: string, abilityName: string) {
let wantAgentInfo = {
wants: [
{
bundleName: bundleName,
abilityName: abilityName
}
],
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags: [wantAgent.WantAgentFlags.CONSTANT_FLAG]
}
wantAgent.getWantAgent(wantAgentInfo, (error, wantAgentObj) => {
if (error.code) {
console.error("[WantAgent]getWantAgent error: " + JSON.stringify(error))
} else {
console.log("[WantAgent]getWantAgent success")
let triggerInfo = {
code: 0
}
wantAgent.trigger(wantAgentObj, triggerInfo, (completeData) => {
console.log("[WantAgent]getWantAgent success, completeData: ", +JSON.stringify(completeData))
})
}
})
}
......
@Entry
@Component
struct Index {
abilityName: string
pageName: string
......
.onClick(() => this.startAbilityViaWantAgent('com.github.hydrotho.router', 'com.example.entry.WantAgentAbility'))
······
}
若你使用 DevEco Studio 进行开发(大概没有人不用),请在侧边栏右键菜单中新建 Ability
和 Page
。通过这种方式,DevEco Studio 将自动配置好 config.json
。
若你选择手动创建新页面,请参考 应用包结构说明(FA 模型)和应用包结构说明(Stage 模型)自行配置 config.json
文件。
这里的 wants
属性也是 Want
类型,具体注意事项请见上文。
WantAgent 模块一般还是其公共事件功能 (SEND_COMMON_EVENT
) 较为常用,更多功能请参考官方文档。
总结
本文介绍了目前 (OpenHarmony v3.2) 北向应用实现页面跳转常见的所有方法,开发者可以根据场景需求自行选择。
一般来说,我们可以这样选择:
- 若使用场景为同一 Ability 内部的不同页面间跳转,选择
@ohos.router
模块。 - 若使用场景为不同 Ability 间跳转,选择
@ohos.ability.featureAbility
模块(FA 模型)或@ohos.application.Ability
模块(Stage 模型)。