如何在SvelteKit纯客户端应用中全局管理在线/离线状态?
SvelteKit PWA 全局在线/离线状态管理最优方案
直接用SvelteKit原生的stores就行,完全没必要用Session或Cookies——在线状态是实时变化的,不需要持久化存储,浏览器本身的navigator.onLine就能提供初始状态,结合stores的响应式特性,刚好能实现全局共享、自动同步的需求。
具体实现步骤
1. 封装全局网络状态Store
在$lib/stores/目录下新建network.js,把监听逻辑写在这里,只需要一次:
import { writable } from 'svelte/store'; // 初始化状态为当前浏览器在线状态 const isOnline = writable(navigator.onLine); // 绑定在线/离线事件,自动更新store function setupNetworkListeners() { const updateOnline = () => isOnline.set(true); const updateOffline = () => isOnline.set(false); window.addEventListener('online', updateOnline); window.addEventListener('offline', updateOffline); // 页面卸载时清理监听,避免内存泄漏 window.addEventListener('beforeunload', () => { window.removeEventListener('online', updateOnline); window.removeEventListener('offline', updateOffline); }); } // 可选:添加心跳检测(解决navigator.onLine误判问题) // 定时请求静态资源验证真实网络连通性 function setupHeartbeat() { const checkInterval = setInterval(async () => { try { const response = await fetch('/favicon.ico', { method: 'HEAD' }); isOnline.set(response.ok); } catch { isOnline.set(false); } }, 5000); // 每5秒检测一次 window.addEventListener('beforeunload', () => clearInterval(checkInterval)); } // 初始化监听和心跳检测 setupNetworkListeners(); setupHeartbeat(); export { isOnline };
2. 全局UI统一处理(顶部菜单、背景图)
在根布局+layout.svelte里导入store,利用Svelte的响应式特性直接绑定样式:
<script> import { isOnline } from '$lib/stores/network.js'; </script> <!-- 顶部菜单 --> <header class:offline={!$isOnline}> <nav> <!-- 菜单内容 --> </nav> </header> <!-- 全局页面容器 --> <div class="page-wrapper" class:offline-bg={!$isOnline}> <slot /> </div> <style> header { background-color: #165DFF; transition: background-color 0.3s ease; } /* 离线时菜单背景色 */ header.offline { background-color: #F53F3F; } .page-wrapper { min-height: 100vh; transition: background-image 0.3s ease; } /* 离线时全局背景图 */ .page-wrapper.offline-bg { background-image: url('/offline-bg.png'); background-size: cover; background-position: center; } </style>
3. 局部组件控制(按钮禁用)
在需要的页面/组件里直接使用$isOnline状态控制按钮状态:
<script> import { isOnline } from '$lib/stores/network.js'; </script> <form> <input type="text" placeholder="输入内容" /> <!-- 离线时禁用提交按钮 --> <button type="submit" disabled={!$isOnline}> {$isOnline ? '提交' : '离线状态无法提交'} </button> </form> <style> button:disabled { opacity: 0.6; cursor: not-allowed; } </style>
为什么不用Session/Cookies?
- 在线状态是实时临时状态,不需要持久化存储,页面刷新后浏览器会自动返回当前真实状态,store会重新初始化
- Session/Cookies是用来存储用户身份、偏好等持久化数据的,用在这里完全是冗余操作,反而会增加不必要的复杂度
内容的提问来源于stack exchange,提问作者ZAky
相关产品推荐
相关产品推荐

