Vue利用visibilitychange事件刷新数据,应对浏览

2021-03-03  本文已影响0人  microkof

前言

在前端开发中,用户经常需要及时收到最新数据,根据紧急程度,有这样的方案:

  1. 实时获取数据:一般是通过WebSocket,比如股市动态,比如聊天,比如2台手机面对面互动,等等。

  2. 每次切回网页,要看到最新数据:这就用到今天说到的visibilitychange事件。

  3. 每隔固定时间获取新数据:定时器就搞定,不多说。

  4. 手动触发更新数据:这个不多说。

什么场景需要“切回网页,就刷新数据”?

现代浏览器对于机能优化都比较苛刻,比如我们做Vue开发的时候,你肯定要打开一个窗口预览,此时你再新建一个浏览器窗口,让原窗口成为后台窗口,接着,你再修改一下Vue项目代码,等几秒,然后让原窗口切回前台,你会发现预览页有跳动,也就是说,尽管原窗口已经收到了DOM修改,但是它只要在后台,就会憋着不改,直到原窗口转为前台,才会对DOM修改,于是就被你看见了修改过程。

这个节能机制听起来不错,但是也有坑,比如setInterval函数,这个定时器就不准了!因为它在后台的时候被挂起了!

另外,对于手机网页,这个问题就更严重了,手机对节能要求更甚,而且浏览器切到后台、锁屏都是极高概率事件!

有些数据无所谓,比如新闻列表,你不需要看到最新的新闻,你只需要在每天固定的时间点刷新下页面就好。但是,比如实时显示服务器时间,就必须要非常准确才行,这时候,我们就用visibilitychange事件好了。

环境

本次测试我用的HBuilderX的wap2app开发的APP,浏览器的话道理都是一样的。

wap2app本身支持显示和隐藏事件

是的,它从APP层级支持这两个事件,但是,这里(https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/12806)说的很清楚:

app.js里写的js代码,运行在本地一个独立的、不可见的Webview中(注意不是运行在首页Webview里)。
如果开发者要操作某个Webview里的dom,那么应该通过plus.webview的evalJS的api,给目标Webview注入一段js代码进行dom操作。

注入代码等于侵入代码,不如js原生开发舒服,所以,咱们还是用visibilitychange事件。

1. 变量docmentVisibility放到Vuex里

代码摘抄,假设我放在了app模块里:

docmentVisibility: false,
  SET_DOCUMENT_VISIBILITY: (state, docmentVisibility) => {
    state.docmentVisibility = docmentVisibility
  },

2. 监听放到App.vue

  created() {
    document.addEventListener('visibilitychange', () => {
      this.$store.commit('app/SET_DOCUMENT_VISIBILITY', document.hidden ? false : true);
    });
  }

3. 找到负责获取服务器时间的组件,改它

最终结果,hour负责保存时钟,minute保存分钟:

import timeApi from '@/api/system/time';

export default {
  data() {
    return {
      timer: null,
      hour: null,
      minute: null,
    };
  },
  computed: {
    docmentVisibility() {
      return this.$store.state.app.docmentVisibility;
    },
  },
  watch: {
    docmentVisibility(newVal) {
      if (!newVal) return;
      clearInterval(this.timer);
      this.getServerTime();
    },
  },
  created() {
    this.getServerTime();
  },
  beforeDestroy() {
    clearInterval(this.timer);
  },
  methods: {
    calcTime(timestamp) {
      this.hour = String(dayjs(timestamp).hour()).padStart(2, '0');
      this.minute = String(dayjs(timestamp).minute()).padStart(2, '0');
    },
    getServerTime() {
      timeApi.serverTimestamp().then((response) => {
        let serverTimestamp = response.data;
        this.calcTime(serverTimestamp);
        this.timer = setInterval(() => {
          serverTimestamp += 1000;
          this.calcTime(serverTimestamp);
        }, 1000);
      });
    },
  },
};

总结

一些业务需要防范浏览器节能挂起,这时候就一定要利用visibilitychange事件刷新数据。

上一篇下一篇

猜你喜欢

热点阅读