Skip to main content

Ionic 页面生命周期

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

🌐 This guide covers how the page life cycle works in an app built with Ionic and Angular.

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

Angular 生命周期事件

🌐 Angular Life Cycle Events

Ionic 采用了 Angular 提供的生命周期事件。你最常用的两个 Angular 事件是:

🌐 Ionic embraces the life cycle events provided by Angular. The two Angular events you will find using the most are:

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

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

🌐 For more info on the Angular Component Life Cycle events, visit their component lifecycle docs.

note

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

Ionic 页面事件

🌐 Ionic Page Events

除了 Angular 生命周期事件之外,Ionic Angular 还提供了一些你可以使用的附加事件:

🌐 In addition to the Angular life cycle events, Ionic Angular provides a few additional events that you can use:

事件名称描述
ionViewWillEnter当要切换到的组件即将动画显示时触发。
ionViewDidEnter当要切换到的组件动画已完成时触发。
ionViewWillLeave当要切换离开的组件即将动画时触发。
ionViewDidLeave当要切换离开的组件动画已完成时触发。

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

🌐 These lifecycles are only called on components directly mapped by a router. This means if /pageOne maps to PageOneComponent, then Ionic lifecycles will be called on PageOneComponent but will not be called on any child components that PageOneComponent may render.

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

🌐 The difference between ionViewWillEnter and ionViewDidEnter is when they fire. The former fires right after ngOnInit but before the page transition begins, and the latter directly after the transition ends.

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

🌐 For ionViewWillLeave and ionViewDidLeave, ionViewWillLeave gets called directly before the transition away from the current page begins, and ionViewDidLeave does not get called until after the new page gets successfully transitioned into (after the new pages ionViewDidEnter fires).

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

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

🌐 How Ionic Handles the Life of a Page

Ionic 有它的路由出口,称为 <ion-router-outlet />。这个出口扩展了 Angular 的 <router-outlet />,并增加了一些额外的功能,以便为移动设备提供更好的体验。

🌐 Ionic has its router outlet, called <ion-router-outlet />. This outlet extends Angular's <router-outlet /> with some additional functionality to enable better experiences for mobile devices.

当一个应用被封装在 <ion-router-outlet /> 中时,Ionic 对导航的处理会有些不同。当你导航到一个新页面时,Ionic 会将旧页面保留在现有的 DOM 中,但会将其从视图中隐藏,并切换到新页面。我们这样做的原因有两个:

🌐 When an app is wrapped in <ion-router-outlet />, Ionic treats navigation a bit differently. When you navigate to a new page, Ionic will keep the old page in the existing DOM, but hide it from your view and transition the new page. The reason we do this is two-fold:

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

页面只有在被“弹出”时才会从 DOM 中移除,例如,通过在 UI 中按返回按钮或浏览器的返回按钮。

🌐 Pages are only removed from the DOM when they are "popped", for instance, by pressing the back button in the UI or the browsers back button.

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

🌐 Because of this special handling, the ngOnInit and ngOnDestroy methods might not fire when you would usually think they should.

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

路由守卫

🌐 Route Guards

在 Ionic 3 中,有几个额外的生命周期方法,它们对于控制何时可以进入页面(ionViewCanEnter)和离开页面(ionViewCanLeave)非常有用。这些方法可以用来保护页面不被未授权用户访问,也可以在不希望用户离开页面时(例如在填写表单期间)保持用户留在页面上。

🌐 In Ionic 3, there were a couple of additional life cycle methods that were useful to control when a page could be entered (ionViewCanEnter) and left (ionViewCanLeave). These could be used to protect pages from unauthorized users and to keep a user on a page when you don't want them to leave (like during a form fill).

这些方法在 Ionic 4 中被删除,转而使用 Angular 的 Route Guards。

🌐 These methods were removed in Ionic 4 in favor of using Angular's Route Guards.

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

🌐 A route guard helps determine if a particular action can be taken against a route. They are classes that implement a certain interface. The CanActivate and CanDeactivate interfaces can be used to implement the same type of logic that the removed events ionViewCanEnter and ionViewCanLeave did.

@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService) {}

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.authService.isAuthenticated();
}
}

要使用此防护,请将其添加到路由定义中的相应参数中:

🌐 To use this guard, add it to the appropriate param in the route definition:

{ path: 'settings', canActivate: [AuthGuard], loadChildren: '...',  }

有关如何使用路由守卫的更多信息,请访问 Angular 的 路由文档

🌐 For more info on how to use route guards, go to Angular's router documentation.

每种生命周期方法的指南

🌐 Guidance for Each Life Cycle Method

以下是有关每个生命周期事件用例的一些提示。

🌐 Below are some tips on use cases for each of the life cycle events.

  • ngOnInit - 初始化你的组件并从不需要在每次后续访问时刷新的服务加载数据。
  • ionViewWillEnter - 由于每次导航到视图时都会调用 ionViewWillEnter(无论是否初始化),这是一个从服务加载数据的好方法。然而,如果你的数据在动画过程中返回,它可能会开始大量的 DOM 操作,这可能会导致一些卡顿的动画。
  • ionViewDidEnter - 如果在使用 ionViewWillEnter 加载数据时看到性能问题,你可以改为在 ionViewDidEnter 中进行数据调用。然而,此事件直到页面对用户可见后才会触发,因此你可能想使用加载指示器或骨架屏,以免过渡完成后内容出现不自然的闪现。
  • ionViewWillLeave - 可以用来进行清理,例如取消订阅 observable。由于在从当前页面导航时 ngOnDestroy 可能不会触发,如果你不希望在屏幕不在视图中时它处于激活状态,可以把你的清理代码放在这里。
  • ionViewDidLeave - 当此事件触发时,你知道新页面已完全转换,因此当视图可见时你通常不会执行的任何逻辑都可以转到此处。
  • ngOnDestroy - ionViewWillLeave 中你不想清理的页面的清理逻辑。