LifeCycle of Browser

为什么页面会需要生命周期?

从浏览器架构中,我们知道了当打开一个Tab标签(页面)时,浏览器会为其创建多个进程,同时也就分配了进程占用的内存。但是随着大量网络应用的的运行,设备的关键资源,比如内存、CPU、电池等都会很容易超额订阅,也就是资源占用过多,得不到释放,最坏的情况就会导致整个应用奔溃。

因此,应用的生命周期是管理资源的关键方式。

生命周期状态以及其转换表

从上图中可以看出,包含了web页面生命周期的状态以及事件

生命周期状态 state

生命周期的状态包含了ActivePassiveHiddenFrozenTerminatedDiscarded

Active

如果页面可见且具有输入焦点,则该页面处于活动状态。可能的先前状态: Passive(通过焦点_focus 事件);可能的下一个状态: Passive(通过blur_事件)

Passive

如果页面可见且没有输入焦点,则该页面处于被动状态。

可能的先前状态:

  • Active(通过blur事件)
  • hidden(通过_visibilitychange_事件);

可能的下一个状态:

  • Active(通过_focus_事件)
  • 隐藏(通过_visibilitychange_事件)

Hidden

如果页面不可见且未被冻结,则该页面处于隐藏状态。

可能的先前状态: Passive(通过_visibilitychange_事件);

可能的下一个状态:

  • Passive(通过_visibilitychange_事件)
  • Frozen(通过freeze事件)
  • Terminated(通过页面pagehide事件)

Frozen

在冻结状态下,浏览器将可冻结任务的执行暂停在页面的任务队列中,直到页面被解冻。这意味着诸如 JavaScript timer 和 fetch callbacks 之类的代码不会运行。已经运行的任务可以完成(最重要的是冻结回调) ,但是它们可以做的事情和可以运行的时间可能受到限制。

浏览器冻结页面是为了保持 CPU/电池/数据的使用; 它们也是为了实现更快的后退/前进导航(避免重新加载整个页面)。

可能的先前状态: hidden(通过freeze事件);

可能的下一个状态:

  • Active(通过resume事件,然后pageshow事件)
  • Passive(通过resume事件,然后pageshow事件)
  • hidden(通过resume事件)

Terminated

一旦页面开始被浏览器从内存中卸载和清除,它就处于终止状态。在此状态下不能启动任何新任务,如果运行时间过长,则可能会终止正在进行的任务。

可能的先前状态: hidden(通过页面pagehide事件)

接下来可能的状态是: 无

Discarded

当页面被浏览器卸载以节省资源时,它处于被丢弃的状态。任何任务、事件回调或任何类型的 JavaScript 都不能在这种状态下运行,因为丢弃通常是在资源约束下发生的,在这种情况下不可能启动新的进程。

在被丢弃的状态下,标签本身(包括标签标题和图标)通常对用户是可见的,即使页面已经消失。

可能的先前状态: Frozen(没有事件触发)

接下来可能的状态是: 无

生命周期事件 events

浏览器分派了大量的事件,但是只有一小部分事件表明页面生命周期状态可能发生了变化。与生命周期相关的事件有focusblurvisibilitychangefreezeresumepageshowpagehidebeforeunloadunload

focus DOM 元素已经获得了焦点。

Note

一个 focus 事件并不一定意味着状态的改变。只有当页面以前没有输入焦点时,它才会发出状态更改的信号

blur DOM 元素失去了焦点。

Note

A blur 事件并不一定意味着状态的改变。如果页面不再具有输入焦点(即页面不只是将焦点从一个元素切换到另一个元素) ,那么它只会发出状态更改的信号

文档的 visibilityState 值已更改。当用户导航到一个新页面,切换标签页,关闭标签页,最小化或关闭浏览器,或者切换移动操作系统上的应用程序时,就会发生这种情况。

freeze

页面刚刚被冻结。页面任务队列中的任何可冻结任务都不会被启动。

resume

浏览器恢复了一个冻结的页面。

pageshow

正在遍历一个会话历史记录条目。这可能是一个全新的页面加载或从缓存取得的页面。如果页面是从缓存获取的,则事件的持久化属性为 true,否则为 false。

pagehide

正在从中遍历会话历史记录条目。如果用户正在导航到另一个页面,并且浏览器能够将当前页面添加到后退缓存中,以便稍后重用,则事件的持久化属性为 true。如果为 true,页面将进入冻结状态,否则将进入终止状态。

beforeunload

即将卸载窗口、文档及其资源。文档仍然可见,此时事件仍然可以取消。

Note

一个 beforeunload 事件应该只用于提醒用户未保存的更改。一旦保存了这些更改,就应该删除该事件。不应该无条件地将它添加到页面中,因为这样做在某些情况下会损害性能。参见legacy APIs section 遗留 api 部分 了解详情。

unload

正在卸载页面。

Note

一个 unload 事件从来不被推荐,因为它不可靠,在某些情况下可能会损害性能。参见legacy APIs section 遗留 api 部分 了解详情。

在代码中观察页面的生命周期

Reference