Vue中监听窗口关闭或刷新执行相关代码

一、简介
有时候,开发者需要知道,用户正在离开页面。常用的方法是监听下面三个事件。

pagehide
beforeunload
unload

窗口关闭事件使用window.beforeunload。

window.onload事件 设置页面加载时执行的动作,即进入页面的时候执行的动作。

window.onunload 已经从服务器上读到了需要加载的新的页面,在即将替换掉当前页面时调用,一般用于设置当离开页面以后执行的动作。

window.onbeforeunload 是正要去服务器读取新的页面时调用,此时还没开始读取,简单来说就是 在离开页面前的,一般用做提醒问你是不是要离开这个页面。

window.beforeunload事件在window.unload事件之前执行。同时注意ajax请求方式必须为同步请求,所以不能使用axios,因为axios不能执行同步请求。

以前,页面被系统切换,以及系统清除浏览器进程,是无法监听到的。开发者想要指定,任何一种页面卸载情况下都会执行的代码,也是无法做到的。为了解决这个问题,就诞生了 Page Visibility API。不管手机或桌面电脑,所有情况下,这个 API 都会监听到页面的可见性发生变化。

这个新的 API 的意义在于,通过监听网页的可见性,可以预判网页的卸载,还可以用来节省资源,减缓电能的消耗。比如,一旦用户不看网页,下面这些网页行为都是可以暂停的。

对服务器的轮询
网页动画
正在播放的音频或视频

二、document.visibilityState

这个 API 主要在document对象上,新增了一个document.visibilityState属性。该属性返回一个字符串,表示页面当前的可见性状态,共有三个可能的值。

hidden:页面彻底不可见。
visible:页面至少一部分可见。
prerender:页面即将或正在渲染,处于不可见状态。
其中,hidden状态和visible状态是所有浏览器都必须支持的。prerender状态只在支持"预渲染"的浏览器上才会出现,比如 Chrome 浏览器就有预渲染功能,可以在用户不可见的状态下,预先把页面渲染出来,等到用户要浏览的时候,直接展示渲染好的网页。

只要页面可见,哪怕只露出一个角,document.visibilityState属性就返回visible。只有以下四种情况,才会返回hidden。

浏览器最小化。
浏览器没有最小化,但是当前页面切换成了背景页。
浏览器将要卸载(unload)页面。
操作系统触发锁屏屏幕。
可以看到,上面四种场景涵盖了页面可能被卸载的所有情况。也就是说,页面卸载之前,document.visibilityState属性一定会变成hidden。事实上,这也是设计这个 API 的主要目的。

另外,早期版本的 API,这个属性还有第四个值unloaded,表示页面即将卸载,现在已经被废弃了。

注意,document.visibilityState属性只针对顶层窗口,内嵌的页面的document.visibilityState属性由顶层窗口决定。使用 CSS 属性隐藏页面(比如display: none;),并不会影响内嵌页面的可见性。

三、document.hidden

由于历史原因,这个 API 还定义了document.hidden属性。该属性只读,返回一个布尔值,表示当前页面是否可见。

当document.visibilityState属性返回visible时,document.hidden属性返回false;其他情况下,都返回true。

该属性只是出于历史原因而保留的,只要有可能,都应该使用document.visibilityState属性,而不是使用这个属性。

四、visibilitychange 事件

只要document.visibilityState属性发生变化,就会触发visibilitychange事件。因此,可以通过监听这个事件(通过document.addEventListener()方法或document.onvisibilitychange属性),跟踪页面可见性的变化。

直接上代码

  methods: {
    // 关闭app 记录用户停留时间入库
    beforeunloadHandler() {
      this._beforeUnload_time = new Date().getTime();
    },
    // 关闭app 记录用户停留时间入库
    unloadHandler(e) {
      this._gap_time = new Date().getTime() - this._beforeUnload_time;
      // debugger
      // 判断是窗口关闭还是刷新
      if (this._gap_time <= 5) {
        // 如果是登录状态,关闭窗口前,移除用户
        if (!this.showLoginButton) {
          //  需要执行的方法
        }
      }
    },
    visibilitychange(e) {
      this._gap_time = new Date().getTime() - this._beforeUnload_time;
      // debugger
      // 判断是窗口关闭还是刷新
      if (this._gap_time <= 5) {
        // 如果是登录状态,关闭窗口前,移除用户
        if (!this.showLoginButton) {
          //  需要执行的方法
        }
      }
    },
}
  mounted() {
    window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
    window.addEventListener('unload', e => this.unloadHandler(e))
    window.addEventListener('visibilitychange', e => this.visibilitychange(e))
    if (this.tpl.productCode === 'WVB_MB_ZYDSJX' && this.$route.query.premium) {
      this.$store.commit('formData/setShowPremium', this.$route.query.premium)
      this.$store.commit('formData/setFinalPremium', this.$route.query.premium)
      this.$store.commit('formData/setQiFlag', false)
    }
  },
  created() {
    let that = this
    document.addEventListener('visibilitychange', function () {
      // 用户离开了当前页面
      if (document.visibilityState === 'hidden') {
          //  需要执行的方法
        debugger
        document.title = '页面可见';
        console.log(111111111111);
      }
      // 用户打开或回到页面
      if (document.visibilityState === 'visible') {
        document.title = '页面可见';
        alert('guanbi')
        debugger
      }
    });
}
  destroyed() {
    window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
    window.removeEventListener('unload', e => this.unloadHandler(e))
    window.removeEventListener('visibilitychange', e => this.visibilitychange(e))
  }

猜你喜欢

转载自blog.csdn.net/weixin_55953988/article/details/125623879