You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Framer-motion退出条件未正确生效问题排查

Framer-motion Exit动画未触发,元素仅隐藏未从DOM移除的解决方案

你的问题核心在于AnimatePresence的exit动画只有当motion组件被从DOM中卸载时才会触发,而原代码中所有卡片始终挂载在DOM里,只是通过animate切换opacity,完全不会触发exit逻辑——哪怕设置了exit={{display: "none"}}也没用,而且display属性本身无法被Framer-motion做过渡动画。

解决步骤:

  1. 条件渲染控制DOM挂载:只有选中的卡片保留在DOM中,未选中的直接不渲染(从DOM移除),让AnimatePresence能检测到元素的卸载动作。
  2. 调整exit动画属性:使用可动画的属性(如opacity、height、padding)完成淡出/收缩效果,动画结束后元素自然从DOM消失。

修改后的代码示例:

import "./styles.css";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";

export default function App() {
  const [selectedCard, setSelectedCard] = useState(null);
  const cards = ["Card 1", "Card 2", "Card 3"];

  return (
    <AnimatePresence>
      <div className="cards">
        {cards.map((card, index) => {
          // 当选中状态存在时,仅渲染选中的卡片
          if (selectedCard !== null && selectedCard !== index) return null;

          return (
            <motion.div
              className="card"
              key={index}
              onClick={() => setSelectedCard(selectedCard === index ? null : index)}
              initial={{ opacity: 1, height: "auto", padding: "1rem" }}
              exit={{ 
                opacity: 0, 
                height: 0, 
                padding: 0,
                transition: { duration: 0.5 } 
              }}
            >
              {card}
            </motion.div>
          );
        })}
      </div>
    </AnimatePresence>
  );
}

关键说明:

  • 当点击卡片后,未选中的卡片通过条件渲染被排除在DOM之外,AnimatePresence会自动触发它们的exit动画。
  • exit动画中加入height: 0和padding: 0,是为了让元素在淡出的同时收缩,避免布局出现跳动;动画结束后元素直接从DOM移除,完全符合你的需求。
  • 如果不需要收缩效果,仅保留opacity: 0的exit动画即可,元素会在淡出后被移除。

内容的提问来源于stack exchange,提问作者Gabi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:15:55