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

如何解决元素淡入插入、淡出移除时快速点击的时序问题?

解决快速点击导致的淡入淡出时序异常问题

问题分析

你的代码核心问题在于同步状态切换与异步操作的时序冲突:

  • 快速点击两次按钮时,第一次点击触发fade-out动画和setTimeout移除任务,但这个移除操作是异步的,需要500ms后才执行;
  • 第二次点击会立即同步切换toggled变量,执行fade-in插入操作;
  • 500ms后,第一次点击的setTimeout任务触发,将已经重新插入的div移除,最终导致异常。

同时,代码中没有状态来标记当前是否处于过渡阶段,无法阻止后续点击提前触发新的逻辑。

解决方案代码

JavaScript(修正版)

const container = document.createElement("div");
let isTransitioning = false; // 标记是否处于动画过渡状态
let isVisible = false; // 记录div当前的可见状态

const button = document.querySelector("button");
button.addEventListener("click", async () => {
  // 如果正在执行过渡动画,直接返回,避免冲突
  if (isTransitioning) return;

  isTransitioning = true;
  if (!isVisible) {
    // 执行淡入逻辑
    container.setAttribute("class", "fade-in");
    button.parentElement.insertBefore(container, button.nextSibling);
    isVisible = true;
    isTransitioning = false;
  } else {
    // 执行淡出逻辑
    container.setAttribute("class", "fade-out");
    // 等待淡出动画完成(用Promise封装异步操作)
    await new Promise(resolve => {
      const handleAnimationEnd = () => {
        container.removeEventListener('animationend', handleAnimationEnd);
        resolve();
      };
      container.addEventListener('animationend', handleAnimationEnd);
    });
    container.remove();
    isVisible = false;
    isTransitioning = false;
  }
});

CSS(保持原逻辑)

div {
    width: 100px;
    height: 100px;
    background-color: black;
}

.fade-in {
    animation: fade-in 500ms linear;
}

@keyframes fade-in {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

.fade-out {
    animation: fade-out 500ms linear;
}

@keyframes fade-out {
    0% {
        opacity: 1;
    }
    
    100% {
        opacity: 0;
    }
}

HTML(修正多余的闭合标签)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="../../CSS/Test.css">
    <script src="../../JS/Test.js" async></script>
    <title>Document</title>
</head>
<body>
    <button> Fade In / Fade Out </button>
</body>
</html>

关键改动说明

  1. 状态锁isTransitioning:
    当开始执行淡入/淡出逻辑时,将此变量设为true,此时用户点击按钮会直接返回,避免在过渡过程中触发新的操作,直到当前动画完成后才解锁。

  2. isVisible替代toggled:
    用明确的可见状态变量替代原有的toggled开关,避免快速点击时同步切换变量导致的逻辑混乱,确保状态判断准确。

  3. 监听animationend事件替代固定延时:
    不再依赖固定的500ms延时,而是监听动画的animationend事件,确保淡出动画真正完成后再执行移除操作,比setTimeout更可靠(比如CSS动画时长修改后无需同步修改JS代码)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:24:14