Ionic 页面生命周期
本指南介绍了使用 Ionic 和 Angular 构建的应用程序中的页面生命周期工作原理。
Angular 生命周期事件
Ionic 采用 Angular 提供的生命周期事件。您将发现最常使用的两个 Angular 事件是
事件名称 | 描述 |
---|---|
ngOnInit | 在组件初始化期间仅触发一次。此事件可用于初始化本地成员并调用仅需执行一次的服务。 |
ngOnDestroy | 在 Angular 销毁视图之前触发。对于清理工作非常有用,例如取消订阅可观察对象。 |
有关 Angular 组件生命周期事件的更多信息,请访问他们的 组件生命周期文档。
使用 ion-nav
或 ion-router-outlet
的组件不应使用 OnPush
更改检测策略。这样做将阻止 ngOnInit
等生命周期钩子触发。此外,异步状态更改可能无法正确呈现。
Ionic 页面事件
除了 Angular 生命周期事件之外,Ionic Angular 还提供了一些您可以使用的其他事件
事件名称 | 描述 |
---|---|
ionViewWillEnter | 当即将路由到的组件动画进入视图时触发。 |
ionViewDidEnter | 当路由到的组件已完成动画时触发。 |
ionViewWillLeave | 当即将离开的组件即将动画时触发。 |
ionViewDidLeave | 当即将离开的组件已完成动画时触发。 |
这些生命周期仅在由路由器直接映射的组件上调用。这意味着如果 /pageOne
映射到 PageOneComponent
,那么 Ionic 生命周期将在 PageOneComponent
上调用,但不会在 PageOneComponent
可能渲染的任何子组件上调用。
ionViewWillEnter
和 ionViewDidEnter
之间的区别在于它们何时触发。前者在 ngOnInit
之后但在页面过渡开始之前触发,而后者在过渡结束之后直接触发。
对于 ionViewWillLeave
和 ionViewDidLeave
,ionViewWillLeave
在从当前页面开始过渡之前直接调用,ionViewDidLeave
直到新页面成功过渡到(新页面 ionViewDidEnter
触发后)才会调用。
Ionic 如何处理页面的生命周期
Ionic 具有自己的路由器出口,称为 <ion-router-outlet />
。此出口扩展了 Angular 的 <router-outlet />
,并提供了一些额外的功能,以实现更适合移动设备的体验。
当应用程序包装在 <ion-router-outlet />
中时,Ionic 对导航的处理略有不同。当您导航到新页面时,Ionic 将保留现有 DOM 中的旧页面,但将其隐藏在您的视图之外,并过渡新页面。我们这样做的原因有两个:
- 我们可以维护旧页面的状态(屏幕上的数据、滚动位置等)。
- 由于页面已存在并且不需要重新创建,因此我们可以提供更平滑的页面过渡。
页面仅在“弹出”时从 DOM 中移除,例如,通过按下 UI 中的后退按钮或浏览器的后退按钮。
由于这种特殊处理,ngOnInit
和 ngOnDestroy
方法可能不会在您通常认为应该触发时触发。
ngOnInit
仅在每次页面首次创建时触发,但不会在导航回页面时触发。例如,在选项卡界面中导航到每个页面,只会调用每个页面的 ngOnInit
方法一次,但在后续访问中不会调用。ngOnDestroy
仅在页面“弹出”时触发。
路由守卫
在 Ionic 3 中,还有一些额外的生命周期方法,这些方法对于控制何时可以进入页面(ionViewCanEnter
)和离开页面(ionViewCanLeave
)非常有用。这些方法可以用于保护页面免受未经授权的用户访问,并在您不希望用户离开页面时将用户留在页面上(例如,在填写表单时)。
这些方法在 Ionic 4 中被移除,转而使用 Angular 的路由守卫。
路由守卫有助于确定是否可以对路由执行特定操作。它们是实现特定接口的类。CanActivate
和 CanDeactivate
接口可以用于实现与已移除事件 ionViewCanEnter
和 ionViewCanLeave
相同类型的逻辑。
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authService.isAuthenticated();
}
}
要使用此守卫,请将其添加到路由定义中的适当参数
{ path: 'settings', canActivate: [AuthGuard], loadChildren: '...', }
有关如何使用路由守卫的更多信息,请访问 Angular 的 路由器文档。
每个生命周期方法的指南
以下是每个生命周期事件的一些用例提示。
ngOnInit
- 初始化组件并从不需要在每次后续访问时刷新的服务中加载数据。ionViewWillEnter
- 由于ionViewWillEnter
在每次导航到视图时(无论是否已初始化)都会调用,因此它是一种从服务中加载数据的良好方法。但是,如果您的数据在动画过程中返回,则它会开始大量的 DOM 操作,这会导致动画变得不流畅。ionViewDidEnter
- 如果您发现使用ionViewWillEnter
加载数据时存在性能问题,则可以在ionViewDidEnter
中执行数据调用。此事件在页面对用户可见之后才会触发,因此您可能需要使用加载指示器或骨架屏幕,这样内容在过渡完成后就不会不自然地闪烁。ionViewWillLeave
- 可用于清理,例如取消订阅可观察对象。由于ngOnDestroy
可能不会在您从当前页面导航时触发,因此如果您不希望在屏幕不可见时将其激活,请将您的清理代码放在此处。ionViewDidLeave
- 当此事件触发时,您就知道新页面已完全过渡进来,因此您可以在这里执行可能不会在视图可见时执行的任何逻辑。ngOnDestroy
- 用于页面的清理逻辑,您不希望在ionViewWillLeave
中清理。