如何在 React 应用中正确实现页面跳转时的预加载动画(Preloader)

6次阅读

如何在 React 应用中正确实现页面跳转时的预加载动画(Preloader)

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 (     
); };

? 对应 CSS(确保支持平滑淡出):

.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 设计哲学的加载体验。

text=ZqhQzanResources