# Page Lifecycle API Android、iOS 和最新的 Windows 系统可以随时自主地停止后台进程,及时释放系统资源。也就是说,网页可能随时被系统丢弃掉。以前的浏览器 API 完全没有考虑到这种情况,导致开发者根本没有办法监听到系统丢弃页面。 为了解决这个问题,W3C 新制定了一个 Page Lifecycle API,统一了网页从诞生到卸载的行为模式,并且定义了新的事件,允许开发者响应网页状态的各种转换。 有了这个 API,开发者就可以预测网页下一步的状态,从而进行各种针对性的处理。Chrome 68 支持这个 API,对于老式浏览器可以使用谷歌开发的兼容库 [PageLifecycle.js](https://github.com/GoogleChromeLabs/page-lifecycle)。 ## 生命周期阶段 网页的生命周期分成六个阶段,每个时刻只可能处于其中一个阶段。 ![](https://www.wangbase.com/blogimg/asset/201811/bg2018110401.png) **(1)Active 阶段** 在 Active 阶段,网页处于可见状态,且拥有输入焦点。 **(2)Passive 阶段** 在 Passive 阶段,网页可见,但没有输入焦点,无法接受输入。UI 更新(比如动画)仍然在执行。该阶段只可能发生在桌面同时有多个窗口的情况。 **(3)Hidden 阶段** 在 Hidden 阶段,用户的桌面被其他窗口占据,网页不可见,但尚未冻结。UI 更新不再执行。 **(4)Terminated 阶段** 在 Terminated 阶段,由于用户主动关闭窗口,或者在同一个窗口前往其他页面,导致当前页面开始被浏览器卸载并从内存中清除。注意,这个阶段总是在 Hidden 阶段之后发生,也就是说,用户主动离开当前页面,总是先进入 Hidden 阶段,再进入 Terminated 阶段。 这个阶段会导致网页卸载,任何新任务都不会在这个阶段启动,并且如果运行时间太长,正在进行的任务可能会被终止。 **(5)Frozen 阶段** 如果网页处于 Hidden 阶段的时间过久,用户又不关闭网页,浏览器就有可能冻结网页,使其进入 Frozen 阶段。不过,也有可能,处于可见状态的页面长时间没有操作,也会进入 Frozen 阶段。 这个阶段的特征是,网页不会再被分配 CPU 计算资源。定时器、回调函数、网络请求、DOM 操作都不会执行,不过正在运行的任务会执行完。浏览器可能会允许 Frozen 阶段的页面,周期性复苏一小段时间,短暂变回 Hidden 状态,允许一小部分任务执行。 **(6)Discarded 阶段** 如果网页长时间处于 Frozen 阶段,用户又不唤醒页面,那么就会进入 Discarded 阶段,即浏览器自动卸载网页,清除该网页的内存占用。不过,Passive 阶段的网页如果长时间没有互动,也可能直接进入 Discarded 阶段。 这一般是在用户没有介入的情况下,由系统强制执行。任何类型的新任务或 JavaScript 代码,都不能在此阶段执行,因为这时通常处在资源限制的状况下。 网页被浏览器自动 Discarded 以后,它的 Tab 窗口还是在的。如果用户重新访问这个 Tab 页,浏览器将会重新向服务器发出请求,再一次重新加载网页,回到 Active 阶段。 ## 常见场景 以下是几个常见场景的网页生命周期变化。 (1)用户打开网页后,又切换到其他 App,但只过了一会又回到网页。 网页由 Active 变成 Hidden,又变回 Active。 (2)用户打开网页后,又切换到其他 App,并且长时候使用后者,导致系统自动丢弃网页。 网页由 Active 变成 Hidden,再变成 Frozen,最后 Discarded。 (3)用户打开网页后,又切换到其他 App,然后从任务管理器里面将浏览器进程清除。 网页由 Active 变成 Hidden,然后 Terminated。 (4)系统丢弃了某个 Tab 里面的页面后,用户重新打开这个 Tab。 网页由 Discarded 变成 Active。 ## 事件 生命周期的各个阶段都有自己的事件,以供开发者指定监听函数。这些事件里面,只有两个是新定义的(`freeze`事件和`resume`事件),其它都是现有的。 注意,网页的生命周期事件是在所有帧(frame)触发,不管是底层的帧,还是内嵌的帧。也就是说,内嵌的`