监听页面更新(vue3)

34 阅读1分钟

新建auto-update.js

/*
 * @Description: 自动更新
 */

// const timeData = 60 * 1000 // 检查间隔时间
import { DialogModel } from '@/components/index'
const timeData = 20 * 1000 // 检查间隔时间
let hidden = false // 页面是否隐藏
let setTimeoutId
let needTip = true // 默认开启提示
let oldScript = []
let newScript = []
const getHtml = async () => {
  const html = await fetch('./').then((res) => res.text()) //读取index html
  return html
}
const parserScript = (html) => {
  const reg = new RegExp(/<script(?:\s+[^>]*)?>(.*?)<\/script\s*>/gi) //script正则
  return html.match(reg) //匹配script标签
}
const init = async () => {
  const html = await getHtml()
  oldScript = parserScript(html)
}

const compareScript = async (oldArr, newArr) => {
  const base = oldArr.length
  // 去重
  const arr = Array.from(new Set(oldArr.concat(newArr)))
  let needRefresh = false
  // 如果新旧length 一样无更新
  // 否则通知更新
  if (arr.length !== base) {
    console.warn('更新了!!!!!!, arr.length !== base', arr.length !== base)
    needRefresh = true
  }
  // for (let i = 0; i < oldArr.length; i++) {
  //   if (oldArr[i] !== arr[i]) {
  //     needRefresh = true
  //     console.warn('更新了!!!!!!, 值不等')
  //     break
  //   }
  // }
  return needRefresh
}

// 自动更新
const autoUpdate = async () => {
  setTimeoutId = setTimeout(async () => {
    const newHtml = await getHtml()
    // console.log("🚀 ~ file: auto-update.js:89 ~ newHtml:", newHtml)
    newScript = parserScript(newHtml)

    // 页面隐藏了就不检查更新
    if (!hidden) {
      const willRefresh = await compareScript(oldScript, newScript)

      if (willRefresh && needTip) {
        // 延时更新,防止部署未完成用户就刷新空白
        setTimeout(() => {
          // ----弹框确认---先简单点弹框确认,可以用注释内的,跳过右下角通知的内容(Step2、3)
          // const result = confirm('发现新版本,点击确定更新')
          // if (result) {
          //   sessionStorage.setItem('version', version)
          //   location.reload() // 刷新当前页
          // }
          // --------------
          DialogModel({
            message: '发现系统版本更新,请刷新页面~',
            cancelable: true,
            cancelTitle: '稍后通知我',
            confirmTitle: '确定更新',
            confirm: () => {
              location.reload()
            },
            cancel: () => {
              needTip = true
            }
          })
        }, 10000)
        needTip = false // 关闭更新提示,防止重复提醒
      }
    }
    if (needTip) {
      console.warn('needTip autoUpdate')
      autoUpdate()
    }
  }, timeData)
}

// 停止检测更新
const stop = () => {
  if (setTimeoutId) {
    clearTimeout(setTimeoutId)
    setTimeoutId = ''
  }
}

// 开始检查更新
const start = async () => {
  init()
  autoUpdate()
  // 监听页面是否隐藏
  document.addEventListener('visibilitychange', () => {
    hidden = document.hidden
    // 页面隐藏了就不检查更新。或者已经有一个提示框了,防止重复提示。
    if (!hidden && needTip) {
      autoUpdate()
    } else {
      stop()
    }
  })
}

export { start }

main.js/main.ts 导入start函数并引用即可

import { start } from '@/utils/auto-update'
// 非生产环境使用
process.env.NODE_ENV == 'development' && start()