跳到主要内容
版本:v7

Ionic 页面生命周期

本指南将介绍在使用 Ionic 和 Angular 构建的应用中,页面生命周期是如何工作的。

展示 Ionic 页面生命周期事件及其顺序的流程图

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 触发后)才会调用。

展示页面过渡期间控制台日志中 Ionic 页面生命周期事件的动画 GIF

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