Ionic 页面生命周期
本指南介绍了页面生命周期在使用 Ionic 和 Angular 构建的应用中如何工作。
¥This guide covers how the page life cycle works in an app built with Ionic and Angular.
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 破坏视图之前触发。对于清理很有用,比如取消订阅可观察对象。 |
有关 Angular 组件生命周期事件的更多信息,请访问他们的 组件生命周期文档。
¥For more info on the Angular Component Life Cycle events, visit their component lifecycle docs.
使用 ion-nav
或 ion-router-outlet
的组件不应使用 OnPush
变更检测策略。这样做将阻止诸如 ngOnInit
之类的生命周期钩子触发。此外,异步状态更改可能无 法正确渲染。
¥Components that use ion-nav
or ion-router-outlet
should not use the OnPush
change detection strategy. Doing so will prevent lifecycle hooks such as ngOnInit
from firing. Additionally, asynchronous state changes may not render properly.
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.
ionViewWillEnter
和 ionViewDidEnter
之间的区别在于它们何时开火。前者在 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.
对于 ionViewWillLeave
和 ionViewDidLeave
,ionViewWillLeave
在离开当前页面的转换开始之前被直接调用,而 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).
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:
-
我们可以维护旧页面的状态(屏幕上的数据、滚动位置等......)
¥We can maintain the state of the old page (data on the screen, scroll position, etc..)
-
我们可以提供返回页面的更平滑的过渡,因为它已经存在并且不需要重新创建。
¥We can provide a smoother transition back to the page since it is already there and doesn't need to be recreated.
仅当页面为 "popped" 时,才会从 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.
由于这种特殊处理,ngOnInit
和 ngOnDestroy
方法可能不会在你通常认为应该触发的情况下触发。
¥Because of this special handling, the ngOnInit
and ngOnDestroy
methods might not fire when you would usually think they should.
ngOnInit
仅在每次新创建页面时触发,但在导航回页面时不会触发。例如,在选项卡界面中的每个页面之间导航只会调用每个页面的 ngOnInit
方法一次,而不会在后续访问中调用。ngOnDestroy
仅当页面 "popped" 时才会触发。
¥ngOnInit
will only fire each time the page is freshly created, but not when navigated back to the page. For instance, navigating between each page in a tabs interface will only call each page's ngOnInit
method once, but not on subsequent visits. ngOnDestroy
will only fire when a page "popped".
路由守卫
¥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.
路由防护有助于确定是否可以针对路由采取特定操作。它们是实现特定接口的类。CanActivate
和 CanDeactivate
接口可用于实现与已删除事件 ionViewCanEnter
和 ionViewCanLeave
相同类型的逻辑。
¥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
- 初始化你的组件并从不需要在每次后续访问时刷新的服务加载数据。¥
ngOnInit
- Initialize your component and load data from services that don't need refreshing on each subsequent visit. -
ionViewWillEnter
- 由于每次导航到视图时都会调用ionViewWillEnter
(无论是否初始化),因此这是从服务加载数据的好方法。但是,如果你的数据在动画期间返回,它可能会启动大量 DOM 操作,这可能会导致一些动画卡顿。¥
ionViewWillEnter
- SinceionViewWillEnter
is called every time the view is navigated to (regardless if initialized or not), it's a good method to load data from services. However, if your data comes back during the animation, it can start lots of DOM manipulation, which can cause some janky animations. -
ionViewDidEnter
- 如果你在加载数据时发现使用ionViewWillEnter
存在性能问题,则可以改为在ionViewDidEnter
中进行数据调用。但是,只有在用户看到页面后才会触发此事件,因此你可能需要使用加载指示器或骨架屏幕,以便在转换完成后内容不会不自然地闪烁。¥
ionViewDidEnter
- If you see performance problems from usingionViewWillEnter
when loading data, you can do your data calls inionViewDidEnter
instead. This event won't fire until after the page is visible by the user, however, so you might want to use either a loading indicator or a skeleton screen, so content doesn't flash in un-naturally after the transition is complete. -
ionViewWillLeave
- 可用于清理,例如取消订阅可观察对象。由于从当前页面导航时ngOnDestroy
可能不会触发,因此如果你不希望在屏幕未显示时激活清理代码,请将清理代码放在这里。¥
ionViewWillLeave
- Can be used for cleanup, like unsubscribing from observables. SincengOnDestroy
might not fire when you navigate from the current page, put your cleanup code here if you don't want it active while the screen is not in view. -
ionViewDidLeave
- 当此事件触发时,你知道新页面已完全转换,因此当视图可见时你通常不会执行的任何逻辑都可以转到此处。¥
ionViewDidLeave
- When this event fires, you know the new page has fully transitioned in, so any logic you might not normally do when the view is visible can go here. -
ngOnDestroy
- 你不想在ionViewWillLeave
中清理的页面的清理逻辑。¥
ngOnDestroy
- Cleanup logic for your pages that you don't want to clean up inionViewWillLeave
.