11# Page Lifecycle API
22
3- Android、iOS 和最新的 Windows 系统上,操作系统可以随时自主地启动和停止后台进程。这是为了及时释放系统资源,提高性能,延长电池的使用时间 。
3+ Android、iOS 和最新的 Windows 系统可以随时自主地停止后台进程,及时释放系统资源。也就是说,网页可能随时被系统丢弃掉。以前的浏览器 API 完全没有考虑到这种情况,导致开发者根本没有办法监听到系统丢弃页面 。
44
5- 以前的浏览器 API 完全没有考虑到这种情况,导致开发者根本没有办法监听到系统丢弃页面。W3C 新制定了一个 Page Lifecycle API,解决这个问题。
6-
7- 这个 API 主要有两个作用,第一是统一了网页从诞生到卸载的行为模式,第二是创建新的 API 和事件,允许开发者响应网页状态的每一种转换。
5+ 为了解决这个问题,W3C 新制定了一个 Page Lifecycle API,统一了网页从诞生到卸载的行为模式,并且定义了新的事件,允许开发者响应网页状态的各种转换。
86
97有了这个 API,开发者就可以预测网页下一步的状态,从而进行各种针对性的处理。Chrome 68 支持这个 API,对于老式浏览器可以使用谷歌开发的兼容库 [ PageLifecycle.js] ( https://github.com/GoogleChromeLabs/page-lifecycle ) 。
108
119## 生命周期阶段
1210
1311网页的生命周期分成六个阶段,每个时刻只可能处于其中一个阶段。
1412
13+ ![ ] ( https://www.wangbase.com/blogimg/asset/201811/bg2018110401.png )
14+
1515** (1)Active 阶段**
1616
1717在 Active 阶段,网页处于可见状态,且拥有输入焦点。
1818
1919** (2)Passive 阶段**
2020
21- 在 Passive 阶段,网页可见,但没有处于输入焦点 ,无法接受输入。UI 更新和动画仍然在执行 。该阶段只可能发生在桌面同时有多个窗口的情况。
21+ 在 Passive 阶段,网页可见,但没有输入焦点 ,无法接受输入。UI 更新(比如动画)仍然在执行 。该阶段只可能发生在桌面同时有多个窗口的情况。
2222
2323** (3)Hidden 阶段**
2424
25- 在 Hidden 阶段,网页不可见,但尚未冻结。UI 界面不再运行 。
25+ 在 Hidden 阶段,用户的桌面被其他窗口占据, 网页不可见,但尚未冻结。UI 更新不再执行 。
2626
2727** (4)Terminated 阶段**
2828
29- 在 Terminated 阶段,网页不可见,由于用户主动关闭窗口,或者在同一个窗口前往其他页面,导致当前页面开始被浏览器卸载并从内存中清除。这个阶段一般由用户手动触发。任何新任务都不可以在此状态下启动,并且如果运行时间太长,正在进行的任务可能会被终止。
29+ 在 Terminated 阶段,由于用户主动关闭窗口,或者在同一个窗口前往其他页面,导致当前页面开始被浏览器卸载并从内存中清除。注意,这个阶段总是在 Hidden 阶段之后发生,也就是说,用户主动离开当前页面,总是先进入 Hidden 阶段,再进入 Terminated 阶段。
30+
31+ 这个阶段会导致网页卸载,任何新任务都不会在这个阶段启动,并且如果运行时间太长,正在进行的任务可能会被终止。
3032
3133** (5)Frozen 阶段**
3234
33- 在 Frozen 阶段,网页冻结,不会再被分配 CPU 计算资源,定时器、回调函数、网络请求、DOM 操作都不会执行,不过正在运行的任务会执行完。通常,Hidden 阶段的页面长时间不打开,就会进入 Frozen 阶段。不过,也有可能,处于可见状态的页面变成 Frozen 阶段。
35+ 如果网页处于 Hidden 阶段的时间过久,用户又不关闭网页,浏览器就有可能冻结网页,使其进入 Frozen 阶段。不过,也有可能,处于可见状态的页面长时间没有操作,也会进入 Frozen 阶段。
3436
35- Frozen 阶段的页面可能会周期性复苏一小段时间,短暂变成 Hidden 状态,允许做一小部分工作 。
37+ 这个阶段的特征是,网页不会再被分配 CPU 计算资源。定时器、回调函数、网络请求、DOM 操作都不会执行,不过正在运行的任务会执行完。浏览器可能会允许 Frozen 阶段的页面,周期性复苏一小段时间,短暂变回 Hidden 状态,允许一小部分任务执行 。
3638
3739** (6)Discarded 阶段**
3840
39- 在 Discarded 阶段,浏览器卸载网页 ,清除该网页的内存占用,以便减少内存占用,一般是在用户没有介入的情况下,由操作系统强制执行。任何类型的新任务或 JavaScript 代码,都不能在此状态下运行,因为这时通常处在在资源限制的状况下,无法启动新进程 。
41+ 如果网页长时间处于 Frozen 阶段,用户又不唤醒页面,那么就会进入 Discarded 阶段,即浏览器自动卸载网页 ,清除该网页的内存占用。不过,Passive 阶段的网页如果长时间没有互动,也可能直接进入 Discarded 阶段 。
4042
41- 通常情况下,如果 Frozen 状态的网页长时间没有唤醒,就会进入 Discarded 阶段。Passive 阶段的网页也可能直接进入 Discarded 阶段 。
43+ 这一般是在用户没有介入的情况下,由系统强制执行。任何类型的新任务或 JavaScript 代码,都不能在此阶段执行,因为这时通常处在资源限制的状况下 。
4244
43- 如果用户重新访问 Discarded 阶段的网页, 浏览器将会重新向服务器发出请求。
45+ 网页被浏览器自动 Discarded 以后,它的 Tab 窗口还是在的。如果用户重新访问这个 Tab 页, 浏览器将会重新向服务器发出请求,再一次重新加载网页,回到 Active 阶段 。
4446
4547## 常见场景
4648
4749以下是几个常见场景的网页生命周期变化。
4850
49- (1)用户打开网页后,又长时间去使用其他 App,系统自动丢弃网页。
51+ (1)用户打开网页后,又切换到其他 App,但只过了一会又回到网页。
52+
53+ 网页由 Active 变成 Hidden,又变回 Active。
54+
55+ (2)用户打开网页后,又切换到其他 App,并且长时候使用后者,导致系统自动丢弃网页。
5056
5157网页由 Active 变成 Hidden,再变成 Frozen,最后 Discarded。
5258
53- (2 )用户打开网页后,又去使用其他 App,然后从任务管理器里面将浏览器清除 。
59+ (3 )用户打开网页后,又切换到其他 App,然后从任务管理器里面将浏览器进程清除 。
5460
5561网页由 Active 变成 Hidden,然后 Terminated。
5662
57- (3 )系统丢弃了某个 Tab 里面的页面后,用户重新打开这个 Tab。
63+ (4 )系统丢弃了某个 Tab 里面的页面后,用户重新打开这个 Tab。
5864
5965网页由 Discarded 变成 Active。
6066
6167## 事件
6268
63- 与生命周期各个阶段相配合的,还有一系列事件。其中,只有两个事件是新定义的,其它都是现存的 。
69+ 生命周期的各个阶段都有自己的事件,以供开发者指定监听函数。这些事件里面,只有两个是新定义的( ` freeze ` 事件和 ` resume ` 事件),其它都是现有的 。
6470
65- 生命周期事件将在所有帧 (frame)触发,不管是底层的帧,还是内嵌的帧。
71+ 注意,网页的生命周期事件是在所有帧 (frame)触发,不管是底层的帧,还是内嵌的帧。也就是说,内嵌的 ` <iframe> ` 网页跟顶层网页一样,都会同时监听到下面的事件 。
6672
67- ** (1) focus 事件**
73+ ### focus 事件
6874
69- ` focus ` 事件在页面获得输入焦点时触发。网页从 Passive 阶段变为 Active 阶段。
75+ ` focus ` 事件在页面获得输入焦点时触发,比如网页从 Passive 阶段变为 Active 阶段。
7076
71- ** (2) blur 事件**
77+ ### blur 事件
7278
73- ` blur ` 事件在页面失去输入焦点时触发。网页从 Active 阶段变为 Passive 阶段。
79+ ` blur ` 事件在页面失去输入焦点时触发,比如网页从 Active 阶段变为 Passive 阶段。
7480
75- ** (3) visibilitychange 事件**
81+ ### visibilitychange 事件
7682
7783` visibilitychange ` 事件在网页可见状态发生变化时触发,一般发生在以下几种场景。
7884
79- - 用户隐藏页面(切换 Tab、最小化浏览器),页面由 Active 阶段变成 Hidden 阶段。
80- - 用户重新访问隐藏的页面,页面由 Hidden 阶段变成 Active 阶段。
81- - 用户关闭页面,页面会先进入 Hidden 阶段,然后进入 Terminated 阶段。
85+ > - 用户隐藏页面(切换 Tab、最小化浏览器),页面由 Active 阶段变成 Hidden 阶段。
86+ > - 用户重新访问隐藏的页面,页面由 Hidden 阶段变成 Active 阶段。
87+ > - 用户关闭页面,页面会先进入 Hidden 阶段,然后进入 Terminated 阶段。
8288
8389可以通过` document.onvisibilitychange ` 属性指定这个事件的回调函数。
8490
85- ** (4) freeze 事件**
91+ ### freeze 事件
8692
8793` freeze ` 事件在网页进入 Frozen 阶段时触发。
8894
@@ -102,11 +108,11 @@ document.onfreeze = function() { … }
102108
103109注意,从 Frozen 阶段进入 Discarded 阶段,不会触发任何事件,无法指定回调函数,只能在进入 Frozen 阶段时指定回调函数。
104110
105- ** (5) resume 事件**
111+ ### resume 事件
106112
107113` resume ` 事件在网页离开 Frozen 阶段,变为 Active / Passive / Hidden 阶段时触发。
108114
109- ` onresume ` 属性指定用户重新访问页面,是的页面离开 Frozen 阶段、进入可用阶段时调用的回调函数。
115+ ` document. onresume` 属性指定用户重新访问页面,是的页面离开 Frozen 阶段、进入可用阶段时调用的回调函数。
110116
111117``` javascript
112118function handleResume (e ) {
@@ -118,23 +124,23 @@ document.addEventListener("resume", handleResume);
118124document .onresume = function () { … }
119125```
120126
121- ** (6) pageshow 事件**
127+ ### pageshow 事件
122128
123129` pageshow ` 事件在用户加载网页时触发。这时,有可能是全新的页面加载,也可能是从缓存中获取的页面。如果是从缓存中获取,则该事件对象的` event.persisted ` 属性为` true ` ,否则为` false ` 。
124130
125- 这个事件的名字有点误导,它跟页面的可见性其实毫无关系,只能浏览器的 History 记录的变化有关。
131+ 这个事件的名字有点误导,它跟页面的可见性其实毫无关系,只跟浏览器的 History 记录的变化有关。
126132
127- ** (7) pagehide 事件**
133+ ### pagehide 事件
128134
129- ` pagehide ` 事件在用户离开当前网页、进入另一个网页时触发。它的前提是浏览器的 History y 记录必须发生变化,跟网页是否可见无关。
135+ ` pagehide ` 事件在用户离开当前网页、进入另一个网页时触发。它的前提是浏览器的 History 记录必须发生变化,跟网页是否可见无关。
130136
131137如果浏览器能够将当前页面添加到缓存以供稍后重用,则事件对象的` event.persisted ` 属性为` true ` 。 如果为` true ` 。如果页面添加到了缓存,则页面进入 Frozen 状态,否则进入 Terminatied 状态。
132138
133- ** (8) beforeunload 事件**
139+ ### beforeunload 事件
134140
135- ` beforeunload ` 事件在窗口或文档即将卸载时触发。该事件发生时,文档仍然可见,此时事件仍可取消 。经过这个事件,网页进入 Terminated 状态。
141+ ` beforeunload ` 事件在窗口或文档即将卸载时触发。该事件发生时,文档仍然可见,此时卸载仍可取消 。经过这个事件,网页进入 Terminated 状态。
136142
137- ** (9) unload 事件**
143+ ### unload 事件
138144
139145` unload ` 事件在页面正在卸载时触发。经过这个事件,网页进入 Terminated 状态。
140146
@@ -170,7 +176,7 @@ if (document.wasDiscarded) {
170176}
171177```
172178
173- 同时,` window ` 对象上会新增` clientId ` 和` discardedClientId ` 两个属性,用来恢复丢弃前的状态。
179+ 同时,` window ` 对象上会新增` window. clientId` 和` window. discardedClientId` 两个属性,用来恢复丢弃前的状态。
174180
175181## 参考链接
176182
0 commit comments