跳至主要内容
版本:v8

Ionic 页面生命周期

本指南介绍了使用 Ionic 和 Angular 构建的应用程序中的页面生命周期工作原理。

Flowchart illustrating the Ionic page life cycle events and their sequence.

Angular 生命周期事件

Ionic 采用 Angular 提供的生命周期事件。您将发现最常使用的两个 Angular 事件是

事件名称描述
ngOnInit在组件初始化期间仅触发一次。此事件可用于初始化本地成员并调用仅需执行一次的服务。
ngOnDestroy在 Angular 销毁视图之前触发。对于清理工作非常有用,例如取消订阅可观察对象。

有关 Angular 组件生命周期事件的更多信息,请访问他们的 组件生命周期文档

注意

使用 ion-navion-router-outlet 的组件不应使用 OnPush 更改检测策略。这样做将阻止 ngOnInit 等生命周期钩子触发。此外,异步状态更改可能无法正确呈现。

Ionic 页面事件

除了 Angular 生命周期事件之外,Ionic Angular 还提供了一些您可以使用的其他事件

事件名称描述
ionViewWillEnter当即将路由到的组件动画进入视图时触发。
ionViewDidEnter当路由到的组件已完成动画时触发。
ionViewWillLeave当即将离开的组件即将动画时触发。
ionViewDidLeave当即将离开的组件已完成动画时触发。

这些生命周期仅在由路由器直接映射的组件上调用。这意味着如果 /pageOne 映射到 PageOneComponent,那么 Ionic 生命周期将在 PageOneComponent 上调用,但不会在 PageOneComponent 可能渲染的任何子组件上调用。

ionViewWillEnterionViewDidEnter 之间的区别在于它们何时触发。前者在 ngOnInit 之后但在页面过渡开始之前触发,而后者在过渡结束之后直接触发。

对于 ionViewWillLeaveionViewDidLeaveionViewWillLeave 在从当前页面开始过渡之前直接调用,ionViewDidLeave 直到新页面成功过渡到(新页面 ionViewDidEnter 触发后)才会调用。

Animated GIF showing Ionic page life cycle events in a console log as a page transition occurs.

Ionic 如何处理页面的生命周期

Ionic 具有自己的路由器出口,称为 <ion-router-outlet />。此出口扩展了 Angular 的 <router-outlet />,并提供了一些额外的功能,以实现更适合移动设备的体验。

当应用程序包装在 <ion-router-outlet /> 中时,Ionic 对导航的处理略有不同。当您导航到新页面时,Ionic 将保留现有 DOM 中的旧页面,但将其隐藏在您的视图之外,并过渡新页面。我们这样做的原因有两个:

  1. 我们可以维护旧页面的状态(屏幕上的数据、滚动位置等)。
  2. 由于页面已存在并且不需要重新创建,因此我们可以提供更平滑的页面过渡。

页面仅在“弹出”时从 DOM 中移除,例如,通过按下 UI 中的后退按钮或浏览器的后退按钮。

由于这种特殊处理,ngOnInitngOnDestroy 方法可能不会在您通常认为应该触发时触发。

ngOnInit 仅在每次页面首次创建时触发,但不会在导航回页面时触发。例如,在选项卡界面中导航到每个页面,只会调用每个页面的 ngOnInit 方法一次,但在后续访问中不会调用。ngOnDestroy 仅在页面“弹出”时触发。

路由守卫

在 Ionic 3 中,还有一些额外的生命周期方法,这些方法对于控制何时可以进入页面(ionViewCanEnter)和离开页面(ionViewCanLeave)非常有用。这些方法可以用于保护页面免受未经授权的用户访问,并在您不希望用户离开页面时将用户留在页面上(例如,在填写表单时)。

这些方法在 Ionic 4 中被移除,转而使用 Angular 的路由守卫。

路由守卫有助于确定是否可以对路由执行特定操作。它们是实现特定接口的类。CanActivateCanDeactivate 接口可以用于实现与已移除事件 ionViewCanEnterionViewCanLeave 相同类型的逻辑。

@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 中清理。