Page Lifecycle & Page Visibility 页面周期和页面可见性

3 篇文章 0 订阅

没有地球 太阳还是会绕。


项目里封装了一个PageWillAppearEvent与原生交互的方法,是调用IOS或安卓的方法,看了一下IOS方法ViewWillAppear是当收到视图在视窗将可见时的通知会呼叫的方法,此外项目还封装了与此类似的JS的监听事件visibilitychange,之前没怎么用过,补一下。

Page Lifecycle

Page Lifecycle 统一了网页从诞生到卸载的行为模式,并且定义了新的事件,允许开发者响应网页状态的各种转换。

一、生命周期阶段

网页的生命周期分成六个阶段,每个时刻只可能处于其中一个阶段。

  1. Active:网页处于可见状态,且拥有输入焦点。

  2. Passive:网页可见,但没有输入焦点。UI更新仍在执行。只可能发生在桌面同时拥有多个窗口的情况。

  3. Hidden:用户桌面被其他窗口占据,页面不可见,但尚未冻结。UI更新不执行。

  4. Terminated:由于用户主动关闭窗口,或在同意窗口前往其他页面,导致但钱页面开始被浏览器卸载并清出内存。这个阶段总是在Hidden阶段之后,也就是说,用户主动离开当前页面,总是先进入Hidden,再是Terminated阶段。

    这个阶段会导致网页卸载,任何新任务都不会在这个阶段启动,并且如果运行时间太长,正在进行的任务可能会被终止。

  5. Frozen:如果网页处于 Hidden 阶段的时间过久,用户又不关闭网页,浏览器就有可能冻结网页,使其进入 Frozen 阶段。不过,也有可能,处于可见状态的页面长时间没有操作,也会进入 Frozen 阶段。

    这个阶段的特征是,网页不会再被分配 CPU 计算资源。定时器、回调函数、网络请求、DOM 操作都不会执行,不过正在运行的任务会执行完。浏览器可能会允许 Frozen 阶段的页面,周期性复苏一小段时间,短暂变回 Hidden 状态,允许一小部分任务执行。

  6. Discarded:如果网页长时间处于 Frozen 阶段,用户又不唤醒页面,那么就会进入 Discarded 阶段,即浏览器自动卸载网页,清除该网页的内存占用。不过,Passive 阶段的网页如果长时间没有互动,也可能直接进入 Discarded 阶段。

    这一般是在用户没有介入的情况下,由系统强制执行。任何类型的新任务或 JavaScript 代码,都不能在此阶段执行,因为这时通常处在资源限制的状况下。

    网页被浏览器自动 Discarded 以后,它的 Tab 窗口还是在的。如果用户重新访问这个 Tab 页,浏览器将会重新向服务器发出请求,再一次重新加载网页,回到 Active 阶段。

二、事件

  • focus  获取焦点时触发
  • blur    失去焦点时触发
  • visibilitychange  在网页可见状态发生变化时触发
  • freeze  在网页进入Frozen阶段时触发,通过document.onfreeze指定回调

    function handleFreeze(e) {
      // Handle transition to FROZEN
    }
    document.addEventListener('freeze', handleFreeze);
    // 或者
    document.onfreeze = function() { ... }
  • resume  在网页离开Frozen阶段,变为Active / Passive / Hidden阶段时触发,通过document.onresume指定回调

    function handleResume(e) {
      // handle state transition FROZEN -> ACTIVE
    }
    document.addEventListener("resume", handleResume);
    // 或者
    document.onresume = function() { ... }

     

  • pageshow  用户加载页面时触发,它跟页面的可见性其实毫无关系,只跟浏览器的 History 记录的变化有关
  • pagehide   用户离开当前页、进入另一个网页时触发。前提是浏览器History记录必须发生变化,跟网页可见性无关
  • beforeunload   在窗口或文档即将卸载时触发。事件发生时,文档仍可见,此时卸载仍可取消。经过这个事件,网页进入 Terminated 状态。
  • unload    页面正在卸载时触发。经过这个事件,网页进入 Terminated 状态。

三、获取当前阶段

如果网页处于 Active、Passive 或 Hidden 阶段,可以通过下面的代码,获得网页当前的状态。

const getState = () => {
  if (document.visibilityState === 'hidden') {
    return 'hidden';
  }
  if (document.hasFocus()) {
    return 'active';
  }
  return 'passive';
};

如果网页处于 Frozen 和 Terminated 状态,由于定时器代码不会执行,只能通过事件监听判断状态。进入 Frozen 阶段,可以监听freeze事件;进入 Terminated 阶段,可以监听pagehide事件。

四、document.wasDiscarded

如果某个选项卡处于 Frozen 阶段,就随时有可能被系统丢弃,进入 Discarded 阶段。如果后来用户再次点击该选项卡,浏览器会重新加载该页面。这时,开发者可以通过判断document.wasDiscarded属性,了解先前的网页是否被丢弃了。

if (document.wasDiscarded) {
  // 该网页已经不是原来的状态了,曾经被浏览器丢弃过
  // 恢复以前的状态
  getPersistedState(self.discardedClientId);
}

同时,window对象上会新增window.clientIdwindow.discardedClientId两个属性,用来恢复丢弃前的状态。 


Page Visibility

一、应用场景

离开页面常用的方法是监听以下三个事件

●  pagehide
●  beforeload
●  unload

但这三个事件在移动端有时候不会触发,因为移动端可以直接将进程切入后台,并杀掉进程。因此诞生了Page Visibility API,对于PC和移动端均适用。这个API通过监听页面的可见性,可预判页面的卸载,可以用来节省资源,例如,如果用户看不见页面,可以关闭轮询、关闭动画、关闭正在播放的音视频。

二、document.visibilityState

document.visibilityState属性返回一个字符串,表示页面当前的可见性状态,三个值:

●  hidden:页面隐藏不可见
●  visible:页面可见
●  prerender:页面即将或正在渲染(不可见)

 其中浏览器必支持hidden和visible,prerender仅由有预渲染功能的浏览器支持。只要页面可见,哪怕只露出一个角,document.visibilityState就为visible。值为hidden有以下场景:

●  浏览器最小化
●  浏览器中当前页面被切成了背景页,被其他页面覆盖
●  浏览器将要卸载(unload)页面
●  操作系统触发锁屏

三、visibilitychange事件

只要document.visibilityState发生变化,就会触发visibilitychange事件,常用的就是通过监听此事件来跟踪页面可见性变化。

●  document.addEventListener()
●  document.onvisibilitychange 

document.addEventListener('visibilitychange', function () {
  // 用户离开了当前页面
  if (document.visibilityState === 'hidden') {
       console.log('页面不可见');
  }

  // 用户打开或回到页面
  if (document.visibilityState === 'visible') {
     console.log('页面可见');
  }
});

四、页面卸载

比较常用的是要监听页面的卸载,分为三种情况:

●  页面可见时,用户关闭 Tab 页或浏览器窗口
●  页面可见时,用户在当前窗口前往另一个页面。
●  页面不可见时,用户或系统关闭浏览器窗口。

这三种情况,都会触发visibilitychange事件。前两种情况,该事件在用户离开页面时触发;最后一种情况,该事件在页面从可见状态变为不可见状态时触发。

visibilitychange事件比pagehidebeforeunloadunload事件更可靠,所有情况下都会触发(从visible变为hidden

 

参考文章:

http://www.ruanyifeng.com/blog/2018/10/page_visibility_api.html
http://www.ruanyifeng.com/blog/2018/11/page_lifecycle_api.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值