SvelteKit 中应在哪里监听 window 的 online 和 offline 事件?
放在根布局的 onMount 中
如果需要在整个应用中显示网络状态提示,通常应在 src/routes/+layout.svelte 的 onMount() 中注册 online 和 offline 事件监听器,并返回清理函数,无需另外编写 onDestroy()。
普通的客户端路由切换通常会保留根布局,监听器也就不会在每次切换页面时重新注册。这里的“启动时注册一次”,是指根布局每次在浏览器中挂载时注册一次;布局销毁后重新挂载时,监听器也会重新注册。
注册事件并返回清理函数
将下面的逻辑合并到根布局现有的 <script> 中:
<script>
import { onMount } from 'svelte';
let online = true;
onMount(() => {
const updateOnlineStatus = () => {
online = navigator.onLine;
};
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
// 读取初始状态,不必等到网络状态发生变化。
updateOnlineStatus();
return () => {
window.removeEventListener('online', updateOnlineStatus);
window.removeEventListener('offline', updateOnlineStatus);
};
});
</script>
在布局中需要显示提示的位置加入:
{#if !online}
<p role="status">当前设备处于离线状态,请检查网络连接。</p>
{/if}
示例使用 Svelte 的传统响应式写法。如果现有组件使用 Svelte 5 的 runes 模式,应将状态声明改为 let online = $state(true);。布局中原有的页面渲染内容应继续保留。
移除监听器时,需要传入注册时使用的同一个函数引用。示例中的两个事件都使用 updateOnlineStatus,因此可以分别用它移除监听器。
为什么使用 onMount?
SvelteKit 默认涉及服务端渲染,而服务端没有浏览器的 window 和 navigator 对象。onMount() 只在组件于浏览器中挂载时执行,适合访问这些 API。
app.html 是页面文档模板,虽然可以在其中放置浏览器脚本,但需要更新 Svelte 界面状态并随组件生命周期清理的逻辑,放在根布局中更便于维护。
onMount() 的回调应保持同步,才能通过返回函数提供清理逻辑。不要为了后续异步操作直接将回调改为 async。
online 不代表服务器一定可访问
online、offline 和 navigator.onLine 反映的是浏览器判断的网络连接状态,不能保证互联网或业务 API 一定可达。例如,设备连接了局域网,业务请求仍可能失败。
这些事件适合用来显示连接状态提示。实际请求仍需处理超时、连接失败和服务端错误,不能仅凭 navigator.onLine 判断请求能否成功。
备注:内容仅供参考。
