移动端复杂动画Hook优化踩坑记录
最近在重构一个移动端电商应用的购物车动画组件时,踩了一个大坑。最初我们直接在组件中使用了多个useEffect来处理动画状态,结果导致性能严重下滑。
问题重现
const CartAnimation = ({ items }) => {
const [isVisible, setIsVisible] = useState(false);
const [animatePosition, setAnimatePosition] = useState({ x: 0, y: 0 });
const [scale, setScale] = useState(1);
useEffect(() => {
if (items.length > 0) {
setIsVisible(true);
// 复杂的动画逻辑
animatePosition.x = calculateX(items);
animatePosition.y = calculateY(items);
setScale(1.2);
setTimeout(() => {
setScale(1);
}, 300);
}
}, [items]);
useEffect(() => {
// 另一个动画监听器
if (isVisible) {
// 复杂的DOM操作
}
}, [isVisible]);
};
优化方案
最终我们重构为一个自定义Hook,将所有动画逻辑集中管理:
const useCartAnimation = (items) => {
const [animationState, setAnimationState] = useState({
isVisible: false,
position: { x: 0, y: 0 },
scale: 1
});
const animate = useCallback(() => {
if (items.length > 0) {
setAnimationState(prev => ({
...prev,
isVisible: true,
position: calculatePosition(items),
scale: 1.2
}));
setTimeout(() => {
setAnimationState(prev => ({
...prev,
scale: 1
}));
}, 300);
}
}, [items]);
return { animationState, animate };
};
// 使用时
const CartComponent = ({ items }) => {
const { animationState, animate } = useCartAnimation(items);
useEffect(() => {
animate();
}, [items, animate]);
return (
<div style={{
transform: `translate(${animationState.position.x}px, ${animationState.position.y}px) scale(${animationState.scale})`
}}>
{/* 动画内容 */}
</div>
);
};
关键优化点
- 使用useCallback避免重复创建函数
- 合并多个useEffect为单个状态管理
- 将动画逻辑提取到独立Hook中复用
- 避免在渲染过程中执行复杂计算
这次重构后,移动端动画流畅度提升约40%,内存占用减少30%。

讨论