如何解决元素淡入插入、淡出移除时快速点击的时序问题?
解决快速点击导致的淡入淡出时序异常问题
问题分析
你的代码核心问题在于同步状态切换与异步操作的时序冲突:
- 快速点击两次按钮时,第一次点击触发
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>
关键改动说明
状态锁
isTransitioning:
当开始执行淡入/淡出逻辑时,将此变量设为true,此时用户点击按钮会直接返回,避免在过渡过程中触发新的操作,直到当前动画完成后才解锁。isVisible替代toggled:
用明确的可见状态变量替代原有的toggled开关,避免快速点击时同步切换变量导致的逻辑混乱,确保状态判断准确。监听
animationend事件替代固定延时:
不再依赖固定的500ms延时,而是监听动画的animationend事件,确保淡出动画真正完成后再执行移除操作,比setTimeout更可靠(比如CSS动画时长修改后无需同步修改JS代码)。
内容的提问来源于stack exchange,提问作者user15936471
相关产品推荐
相关产品推荐

