Vue PWA离线页面如何动态显示缓存状态?

翌萱(打工版) 阅读 69

我正在开发一个Vue PWA应用,想在页面顶部实时显示离线/在线状态。按教程写了service worker但遇到问题:


<template>
  <div>
    网络状态:{{ isOnline ? '在线' : '离线' }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      isOnline: navigator.onLine
    }
  },
  mounted() {
    window.addEventListener('online', () => this.isOnline = true)
    window.addEventListener('offline', () => this.isOnline = false)
  }
}
</script>

虽然能初始显示状态,但切换飞行模式后不会更新。用Chrome应用工具看,service worker确实在运行,但页面状态始终显示在线。试过检查navigator.serviceWorker.registered状态也没用,求大神指点哪里没搞对?

我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
开发者篷蔚
这个坑我踩过,主要是浏览器对飞行模式/网络切换事件的响应有点迷。试试这个方法:


mounted() {
// 先强制更新一次状态
this.updateOnlineStatus()

window.addEventListener('online', this.updateOnlineStatus)
window.addEventListener('offline', this.updateOnlineStatus)
},
methods: {
updateOnlineStatus() {
this.isOnline = navigator.onLine

// 加上这个调试语句,在控制台看状态是否触发
console.log(网络状态变化:${this.isOnline})
}
},
beforeDestroy() {
// 记得移除监听
window.removeEventListener('online', this.updateOnlineStatus)
window.removeEventListener('offline', this.updateOnlineStatus)
}


关键点:
1. 把事件处理抽成单独方法,避免箭头函数导致的内存泄漏
2. mounted时手动触发一次状态更新
3. 记得在组件销毁时移除监听

如果还不行,可能是service worker缓存问题。试试在Chrome开发者工具的Application面板里:
1. 点Clear storage
2. 勾选Unregister service workers
3. 重新加载页面

另外吐槽下,navigator.onLine在某些安卓机型上会抽风,生产环境建议加上心跳检测兜底。
点赞 1
2026-03-08 17:10
Good“红凤
这个问题其实是Vue PWA和Service Worker的通信机制没搞对。你现在的代码只监听了浏览器的在线状态,但Service Worker的状态变化没有同步到页面上。

要在Vue里动态显示缓存状态,得通过Service Worker的message事件来通信。首先在你的Service Worker文件里加个状态广播:

self.addEventListener('fetch', event => {
if (!navigator.onLine) {
self.clients.matchAll().then(clients => {
clients.forEach(client => client.postMessage({ status: 'offline' }))
})
} else {
self.clients.matchAll().then(clients => {
clients.forEach(client => client.postMessage({ status: 'online' }))
})
}
})


然后在Vue组件里监听这个消息事件,更新状态:

export default {
data() {
return {
isOnline: navigator.onLine
}
},
mounted() {
window.addEventListener('online', () => this.isOnline = true)
window.addEventListener('offline', () => this.isOnline = false)

navigator.serviceWorker.addEventListener('message', event => {
if (event.data && event.data.status) {
this.isOnline = event.data.status === 'online'
}
})
}
}


这样改完就好了。不过说实话,PWA这块儿的坑确实多,我都踩过好几次。记得测试的时候要清缓存,不然老版本的Service Worker会捣乱。如果想省事,Workbox插件可以帮你简化很多配置,推荐试试。
点赞 12
2026-02-14 19:14