Svelte中document.readyState在Chrome与Firefox的表现差异问题
问题原因分析
核心矛盾在于Svelte的onMount执行时机与浏览器document.readyState的状态同步问题:
- Chrome页面加载速度快,当
onMount执行(组件挂载完成)时,document.readyState已经处于complete状态。如果代码仅通过绑定document.onreadystatechange事件监听状态变化,此时该事件已经触发过,不会再执行回调,导致加载屏无法隐藏。 - Firefox加载速度相对较慢,
onMount执行时document.readyState可能还处于loading或interactive阶段,绑定事件后,当状态变为complete时回调会正常触发,加载屏能正常隐藏。 - 普通
index.html中的代码在全局上下文执行,会在页面加载早期完成事件绑定,无论浏览器加载快慢都能捕捉到readyState的变化,因此不会出现兼容性问题。
解决方案
在onMount中同时处理两种场景:先检查当前readyState是否已经是complete,再绑定事件监听后续变化;同时结合2秒延迟,确保加载屏至少显示2秒。
示例代码
<script> import { onMount } from 'svelte'; let showLoader = true; onMount(() => { // 监听页面加载完成的Promise const pageLoaded = new Promise(resolve => { // 先检查当前状态,避免Chrome已完成加载的情况 if (document.readyState === 'complete') { resolve(); return; } const handleReadyStateChange = () => { if (document.readyState === 'complete') { document.removeEventListener('readystatechange', handleReadyStateChange); resolve(); } }; document.addEventListener('readystatechange', handleReadyStateChange); }); // 至少显示2秒的Promise const minDisplayTime = new Promise(resolve => setTimeout(resolve, 2000)); // 两个条件都满足后隐藏加载屏 Promise.all([pageLoaded, minDisplayTime]).then(() => { showLoader = false; }); // 组件卸载时清理事件监听,避免内存泄漏 return () => { document.removeEventListener('readystatechange', handleReadyStateChange); }; }); </script> {#if showLoader} <div class="loader-screen"> <!-- 加载动画或文案 --> 页面加载中... </div> {/if} <style> .loader-screen { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-color: #fff; display: flex; align-items: center; justify-content: center; z-index: 9999; } </style>
关键细节
- 先检查当前状态:避免Chrome中
onMount执行时页面已加载完成,事件监听错过触发时机的问题。 - 合并两个条件:用
Promise.all确保加载屏既不会在页面未加载完成时提前消失,也不会显示时间不足2秒。 - 清理事件监听:组件卸载时移除
readystatechange监听,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Abhay Salvi
相关产品推荐
相关产品推荐

