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

DOM元素加载与移除时的CSS动画实现问题(React环境)

解决方案:只用CSS + React状态实现元素的展开/收缩动画

嘿,完全可以只用CSS搞定这个需求!而且结合React的状态管理,比用jQuery更贴合你的项目场景哦~下面一步步来实现:

1. 定义两个CSS关键帧动画

一个负责元素加载时的展开(就是你现有的动画,改个名字更清晰),一个负责移除时的收缩:

/* 展开动画:和你原来的逻辑一致 */
@keyframes widthExpand {
  0% { width: 0; }
  20% { width: 40px; }
  40% { width: 80px; }
  60% { width: 120px; }
  80% { width: 160px; }
  100% { width: 200px; }
}

/* 收缩动画:反向的展开逻辑 */
@keyframes widthShrink {
  0% { width: 200px; }
  20% { width: 160px; }
  40% { width: 120px; }
  60% { width: 80px; }
  80% { width: 40px; }
  100% { width: 0; }
}

2. 编写对应的CSS类

给元素设置基础样式,再分别定义展开和收缩的动画类,注意用forwards让动画结束后保持最终状态:

.item-popup-list {
  /* 基础样式:默认宽度0,避免初始闪烁 */
  width: 0;
  /* 按需添加其他样式,比如背景、边框 */
  background: #f5f5f5;
  border: 1px solid #ddd;
  overflow: hidden; /* 防止内容溢出 */
}

/* 展开动画类 */
.item-popup-list.expand {
  animation: widthExpand 200ms ease forwards;
}

/* 收缩动画类 */
.item-popup-list.shrink {
  animation: widthShrink 200ms ease forwards;
}

3. 在React组件中用状态控制类名切换

核心思路是:用状态控制元素是否可见,以及当前是展开还是收缩状态。当需要移除元素时,先触发收缩动画,等动画结束后再真正从DOM中移除元素。

方法一:监听animationend事件(更推荐)

不用硬编码动画时长,监听动画结束事件来触发元素移除,更灵活:

import { useState, useEffect } from 'react';

function PopupList() {
  const [isVisible, setIsVisible] = useState(true);
  const [isShrinking, setIsShrinking] = useState(false);

  // 触发收缩动画
  const handleRemove = () => {
    setIsShrinking(true);
  };

  // 动画结束后处理:如果是收缩动画,就隐藏元素
  const handleAnimationEnd = () => {
    if (isShrinking) {
      setIsVisible(false);
    }
  };

  // 元素重新显示时,重置为展开状态
  useEffect(() => {
    if (isVisible) {
      setIsShrinking(false);
    }
  }, [isVisible]);

  return (
    <>
      {isVisible && (
        <div 
          className={`item-popup-list ${isShrinking ? 'shrink' : 'expand'}`}
          onAnimationEnd={handleAnimationEnd}
        >
          这是弹出列表的内容
        </div>
      )}
      <button onClick={handleRemove}>移除列表</button>
    </>
  );
}

export default PopupList;

方法二:用setTimeout配合动画时长

如果不想监听事件,也可以用定时器,注意时间要和CSS动画时长一致:

import { useState, useEffect } from 'react';

function PopupList() {
  const [isVisible, setIsVisible] = useState(true);
  const [isShrinking, setIsShrinking] = useState(false);

  const handleRemove = () => {
    setIsShrinking(true);
    // 定时器时间和动画时长(200ms)保持一致
    setTimeout(() => {
      setIsVisible(false);
    }, 200);
  };

  useEffect(() => {
    if (isVisible) {
      setIsShrinking(false);
    }
  }, [isVisible]);

  return (
    <>
      {isVisible && (
        <div 
          className={`item-popup-list ${isShrinking ? 'shrink' : 'expand'}`}
        >
          这是弹出列表的内容
        </div>
      )}
      <button onClick={handleRemove}>移除列表</button>
    </>
  );
}

export default PopupList;

为什么不用jQuery?

你的项目基于React,它是状态驱动UI的框架,用状态切换类名的方式完全符合React的设计理念,不需要引入jQuery这样的DOM操作库——既减少了依赖,也能避免React和jQuery的DOM操作冲突,代码更干净易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:51:33