
framer motion 中组件卸载时无法触发出场动画,根本原因是缺少 `animatepresence` 包裹和唯一 `key` 属性;本文详解其原理、正确用法及常见陷阱。
在 Framer Motion 中,exit 动画(即组件从 DOM 中移除前的过渡动画)不会自动生效,即使你已正确配置了 initial、animate 和 exit 属性。这是因为 React 的渲染机制本身不提供“组件即将卸载且允许异步等待”的生命周期钩子——而退出动画恰恰需要这种能力:组件必须在动画完成后再真正从 DOM 中移除。
要启用退出动画,必须满足两个缺一不可的前提条件:
- ✅ 将需动画退出的组件包裹在
中; - ✅ 该组件(及其同级兄弟组件,如存在多个条件渲染项)必须拥有稳定且唯一的 key 属性。
以下是正确实现示例:
闪灵CMS企业建站系统是淄博闪灵网络科技有限公司开发的一款专门为企业建站提供解决方案的产品,前端模板样式主打HTML5模板,以动画效果好、页面流畅、响应式布局为特色,程序主体采用PHP+MYSQL构架,拥有独立自主开发的一整套函数、标签系统,具有极强的可扩展性,设计师可以非常简单的开发出漂亮实用的模板。系统自2015年发布第一个版本以来,至今已积累上万用户群,为上万企业提供最优质的建站方案。
import { AnimatePresence, motion } from "framer-motion";
function App() {
const [isVisible, setIsVisible] = useState(true);
return (
<div>
<button onClick={() => setIsVisible(!isVisible)}>
{isVisible ? "Hide" : "Show"}
</button>
{/* ✅ 关键:必须用 AnimatePresence 包裹 */}
<AnimatePresence>
{isVisible && (
// ✅ 关键:必须设置唯一且稳定的 key
<motion.div
key="content-block" // 不可用 index 或随机值;推荐语义化字符串
initial={{ opacity: 0, y: -50 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 50, transition: { duration: 0.3 } }}
style={{
padding: "1rem",
background: "#f0f9ff",
borderRadius: "8px",
margin: "1rem 0"
}}
>
Very Code...
</motion.div>
)}
</AnimatePresence>
</div>
);
}⚠️ 常见错误与注意事项:
错误 1:遗漏 AnimatePresence
即使 exit 配置完整,没有 AnimatePresence,exit 将完全被忽略——组件会立即卸载,无任何动画。错误 2:缺失或无效的 key
key 必须是字符串类型,且在同一 AnimatePresence 内唯一且稳定。避免使用 Math.random()、Date.now() 或数组 index(尤其在列表重排时易导致 key 冲突或复用,破坏动画逻辑)。错误 3:在非条件渲染场景下误用
AnimatePresence 仅对因 React 条件渲染(如 &&、ternary、map)导致的挂载/卸载生效。若通过 CSS display: none 或 visibility: hidden 控制显隐,则属于状态切换,应使用 animate + transition,而非 exit。-
进阶提示:自定义退出完成回调
可通过 onExitComplete 属性监听退出动画结束:<motion.div key="item-1" exit={{ opacity: 0, scale: 0.8 }} onExitComplete={() => console.log("Exit finished!")} />
总结:Framer Motion 的退出动画不是“开箱即用”的特性,而是依赖 AnimatePresence + key 的显式契约。理解这一设计背后对 React 渲染模型的补充逻辑,是写出可预测、高性能交互动画的关键基础。









