1、Navigation生命周期管理原理
Navigation作为路由容器,其生命周期承载在NavDestination组件上,以组件事件的形式开放。其生命周期大致可分为三类,自定义组件生命周期、通用组件生命周期和自有生命周期。
自定义组件生命周期函数
其中,aboutToAppear和aboutToDisappear是自定义组件的生命周期(NavDestination外层包含的自定义组件),由于NavDestination的页面依赖自定义组件builder去构造,所以这两个生命周期也可以被开发者使用,但这两个生命周期实际上是在NavDestination页面创建导销毁的完整生命周期之外的,所以也会存在一些限制和差异,如:无法通过NavDestination的无感监听感知、在aboutToAppear中做栈操作会跟上一次栈操作合并成一次等。
- aboutToAppear
在创建自定义组件后,执行其build()函数之前执行(NavDestination创建之前),不建议在这里做栈操作。
- aboutToDisappear
自定义组件析构销毁之前执行,不允许在该方法中改变状态变量。
通用组件生命周期函数
OnAppear和OnDisappear是组件的通用生命周期,为NavDestination组件上下UI树时触发。
- onAppear
通用生命周期事件,NavDestination组件挂载到组件树时执行。
- onDisappear
通用生命周期事件,NavDestination组件从组件树上卸载时执行。
NavDestination独有生命周期:
- onWillAppear
NavDestination创建后,挂载到组件树之前执行,在该方法中更改状态变量会在当前帧显示生效。
- onWillShow
NavDestination组件布局显示之前执行,此时页面不可见(应用切换到前台不会触发)。
- onShown
NavDestination组件布局显示之后执行,此时页面已完成布局。
- onActive
NavDestination处于激活态(处于栈顶可操作,且上层无特殊组件遮挡)触发。
- onWillHide
NavDestination组件触发隐藏之前执行(应用切换到后台不会触发)。
- onInactive
NavDestination组件处于非激活态(处于非栈顶不可操作,或处于栈顶时上层有特殊组件(全局弹窗、模态、OverlayManager)遮挡)触发。
- onHidden
NavDestination组件触发隐藏后执行(非栈顶页面push进栈,栈顶页面pop出栈或应用切换到后台)。
- onWillDisappear
NavDestination组件即将销毁之前执行,如果有转场动画,会在动画前触发(栈顶页面pop出栈)。
特殊的生命周期:
除了以上介绍的常规生命周期外,Navdestination还具备两个特殊的生命周期:
- onNewParam
该生命周期会在Navdestination通过单例跳转再次回到栈顶时触发,并接收到新的param参数。
- onResult
该生命周期会在Navdestination通过back事件或pop操作回到栈顶时触发,如果是其他Navdestination通过pop携带返回参数回到栈顶时,onResult会接收到返回参数。
整体生命周期时序可以参考下图所示:
这里展示了一个页面进栈出栈的相对生命周期(C页面相对于B和A)和绝对生命周期(C页面),其中B页面是Dialog页面(后面详细介绍),C页面是栈顶页面,A和B页面是栈中页面。

按照状态的切换流图如下:

2、生命周期用法示例
上一节中讲解了Navigation路由框架生命周期的原理。开发者可以在对应的生命周期中增加逻辑,当路由操作触发对应的生命周期后,逻辑会对应的执行。本节将会通过页面跳转与半模态激活的功能,来演示两对常用的生命周期:onShown、onHidden 和 onActive、onInActive。
首先,定义如下的半模态
// LifecycleNavDest.ets
// 用以拉起一个半模态
@Builder
function sheetBuilder() {
SheetDemo()
}
@Component
struct SheetDemo {
build() {
Column() {
Text('半模态示例')
}
.width('100%')
.height('100%')
}
}
如下的示例演示了通过路由push操作,与激活、隐藏半模态来触发这两组生命周期的行为:
// LifecycleNavDest.ets
@Component
struct LifecycleNavDestination {
name: string = 'NA'
stack: NavPathStack = new NavPathStack()
@State isActive_: boolean = false;
@State isOnShown_: boolean = false;
@State showSheet_: boolean = false;
build() {
NavDestination() {
Button() {
// 根据@State修饰的变量isOnShown_来更新显示的内容
Text('当前页面的active状态: ' + (this.isActive_ ? 'onActive' : 'onInActive'))
.fontColor(this.isActive_ ? Color.White : undefined)
}
.height(42)
.width(330)
.margin(7)
.backgroundColor(this.isActive_ ? '# 0cc' : '# ccc')
Button() {
// 根据@State修饰的变量isActive_来更新显示的内容
Text('当前页面的show状态: ' + (this.isOnShown_ ? 'onShown' : 'onHidden'))
.fontColor(this.isOnShown_ ? Color.White : undefined)
}
.height(42)
.width(330)
.margin(7)
.backgroundColor(this.isOnShown_ ? '# 0cc' : '# ccc')
Button('跳转到pageOne')
.width(330)
.margin(7)
.onClick(() => {
// 发生了页面跳转,会触发当前页面的onInActive和onHidden
this.stack.pushPath({name: 'lifecyclePageOne'})
})
Button('开启半模态')
.width(330)
.margin(7)
.onClick(() => {
// 拉起一个半模态页面,当前NavDestination页面仍然可见,因此不会触发onHidden。但会触发onInActive
this.showSheet_ = !this.showSheet_;
})
.bindSheet($$this.showSheet_, sheetBuilder(), {
detents: [SheetSize.MEDIUM, SheetSize.LARGE, 600],
preferType: SheetType.BOTTOM,
})
}
.onReady((context: NavDestinationContext) => {
console.log('AceNavigation', 'LifecycleNavDestination', 'onReady')
// 在onReady回调中获取NavPathStack实例
this.stack = context.pathStack
})
.onShown(() => {
console.log('AceNavigation', 'LifecycleNavDestination', 'onShown')
// 在onShown生命周期触发时,修改状态变量isOnShown_为true
this.isOnShown_ = true;
})
.onHidden(() => {
console.log('AceNavigation', 'LifecycleNavDestination', 'onHidden')
// 在onHidden生命周期触发时,修改状态变量isOnShown_为false
this.isOnShown_ = false;
})
.onActive(() => {
console.log('AceNavigation', 'LifecycleNavDestination', 'onActive')
// 在onActive生命周期触发时,修改状态变量isActive_为true
this.isActive_ = true;
})
.onInactive(() => {
console.log('AceNavigation', 'LifecycleNavDestination', 'onInactive')
// 在onActive生命周期触发时,修改状态变量isActive_为false
this.isActive_ = false;
})
}
}
可以看到,当进行push操作后,active与onshown会同时触发(对应于页面中上两个按钮置灰);

当进行拉起半模态操作后,仅有active按钮会被置灰(表示当前NavDestination可见但不处于Active状态)。

315

被折叠的 条评论
为什么被折叠?



