
在 react 单页应用(spa)中,直接混用 jquery 的 `$(window).on('load')` 无法响应路由跳转,导致预加载器不消失;应改用 react 生命周期或路由事件监听 + 状态控制来统一管理显示与隐藏逻辑。
在 React 中实现预加载动画(Preloader),关键在于理解 SPA 的运行机制:页面不会真正“刷新”,HTML 文档不会重新加载,因此原生 window.load 或 jQuery 的 $(window).on('load') 仅在首次完整加载时触发,后续路由跳转(如点击 Home 链接)不会再次触发该事件。你当前代码中混合使用 jQuery 与 React(如 useEffect + document.querySelector),不仅破坏了 React 的声明式更新原则,还易引发 DOM 状态不一致、CSS 丢失、重复挂载等问题。
✅ 正确做法:使用 React 状态 + 路由监听(推荐 react-router-dom v6+)实现可控的 Preloader:
// Preloader.tsx
import { useState, useEffect } from 'react';
import { useLocation, useNavigation } from 'react-router-dom';
export const Preloader = () => {
const [isVisible, setIsVisible] = useState(true);
const location = useLocation();
const navigation = useNavigation();
// 监听路由跳转开始(navigation.state === 'loading')
useEffect(() => {
if (navigation.state === 'loading') {
setIsVisible(true); // 进入新路由时显示加载器
}
}, [navigation.state]);
// 监听路由跳转完成(location 变化后延迟隐藏,确保过渡自然)
useEffect(() => {
const timer = setTimeout(() => {
setIsVisible(false);
}, 300); // 匹配 CSS fade-out 动画时长(如 300ms)
return () => clearTimeout(timer);
}, [location]);
if (!isVisible) return null;
return (
<div className="preloader">
<div className="ball ball-1"></div>
<div className="ball ball-2"></div>
<div className="ball ball-3"></div>
</div>
);
};? 对应 CSS(确保支持平滑淡出):
把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
.preloader {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #fff;
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
transition: opacity 0.3s ease, visibility 0.3s ease;
}
.preloader:not(:root) {
opacity: 1;
visibility: visible;
}
.preloader.hidden {
opacity: 0;
visibility: hidden;
}⚠️ 注意事项:
- ❌ 不要手动操作 DOM(如 document.querySelector(...).style.display = "none"),这会绕过 React 渲染流程,导致样式丢失或状态不同步;
- ❌ 避免在组件中引入 jQuery,React 的虚拟 DOM 与 jQuery 的直接 DOM 操作存在生命周期冲突;
- ✅ 若使用 BrowserRouter,确保 挂载在 Router 内部且位置合理(通常置于 App 根组件顶层);
- ✅ 如需更精细控制(如仅对异步数据加载显示 Preloader),可结合 Suspense + lazy 或自定义 useAsyncLoader Hook。
总结:Preloader 在 React 中不是“一次性的页面加载装饰”,而是受路由状态驱动的 UI 组件。用状态 + 路由钩子替代全局事件监听,才能真正实现响应式、可维护、符合 React 设计哲学的加载体验。

















