React路由切换时过渡动画卡顿怎么办?
大家好,我在用React Router做页面切换过渡动画时遇到问题。我给路由组件加了Animate.css的fadeIn动画,但切换页面时动画有时候会卡顿或者直接跳过。我尝试在useEffect里手动添加类名,但感觉时机没把控好。
代码是这样的:
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
function Page() {
const location = useLocation();
useEffect(() => {
const element = document.querySelector('.page-container');
element?.classList.add('animated', 'fadeIn');
return () => element?.classList.remove('animated', 'fadeIn');
}, [location]);
return <div className="page-container">...</div>;
}
我猜问题可能出在组件卸载太快导致动画没执行完就被销毁了?或者useEffect里的DOM操作有什么隐患?有经验的前辈能指导下更优雅的解决方案吗?
要解决这个问题,可以考虑用一个专门处理过渡动画的库,比如
react-transition-group,它能帮你更好地控制组件的进入和退出动画。具体做法是给路由组件包一层CSSTransition,通过它的生命周期钩子来确保动画完整执行。下面是一个改进后的代码示例:
然后在CSS里定义动画的关键帧,比如这样:
这里的关键点是
CSSTransition会在组件进入和退出时自动添加对应的类名(比如page-enter、page-enter-active),你可以根据这些类名定义CSS动画。timeout属性要和CSS里定义的动画时间一致,否则可能会出现动画不完整或者卡顿的情况。至于你之前用
useEffect手动操作DOM的方式,其实不是特别推荐,因为React本身的数据流设计就不建议直接操作DOM,容易引发各种问题,比如你提到的时机不对或者动画被跳过。最后吐槽一句,前端做动画真的挺烦的,尤其是涉及到路由切换的时候,稍微不注意就会显得很卡顿,不过用对工具后会轻松很多。
可以试试这样,用CSS动画配合React的状态管理来控制动画的完整流程。具体来说,就是给路由切换加一个过渡状态,等动画完成后再真正卸载组件。下面是一个改进的思路:
首先,你需要一个包裹组件来处理动画逻辑。这个组件会在路由切换时先触发动画,等动画结束再卸载旧的页面。
然后在CSS里定义好动画规则,比如:
这里的重点是通过
onAnimationEnd来监听动画的结束事件,确保动画完整执行后再切换页面。这样就避免了组件被提前卸载的问题。另外一个小建议,直接操作DOM的方式虽然能跑,但不太好维护,建议尽量用React的状态和生命周期来控制动画。如果以后项目复杂度增加,这种方式会更容易扩展。
对了,如果你觉得手写这些太麻烦,也可以看看
react-transition-group这个库,它专门用来处理这种过渡动画的场景,封装得很好用。不过自己实现一遍也能加深理解,看你需求吧!