从事件中调用clearTimeout()无效的问题排查
clearTimeout失效的原因及修复方案
失效原因
问题核心在于transitionend事件的重复触发:
你的CSS中设置了transition: all 1s ease-in-out 0s,当给div添加black类时,背景色(background-color)和边框(border)两个样式属性都发生了变化,这两个属性的过渡动画完成后,会分别触发一次transitionend事件。
每次触发transitionend,都会重新给全局变量timeout赋值一个新的定时器ID——第一次触发生成的定时器ID会被第二次的覆盖。当你按下键盘执行clearTimeout(timeout)时,只能清除最后一次创建的定时器,但第一次创建的定时器仍在后台运行,到时间后依然会执行classList.remove("black"),导致样式被移除。
修复方案
方案1:让transitionend事件只触发一次
使用addEventListener并配置once: true,确保每次点击后transitionend只执行一次:
const box = document.querySelector("div") let timeout box.onclick = () => { box.classList.add("black") // 绑定一次性监听,触发后自动移除 box.addEventListener('transitionend', handleTransitionEnd, { once: true }) } function handleTransitionEnd() { timeout = setTimeout(() => { box.classList.remove("black") }, 3000) } window.onkeydown = () => { clearTimeout(timeout) }
方案2:只监听目标属性的transitionend事件
在transitionend回调中判断触发事件的属性名,只处理你关心的属性(比如背景色):
const box = document.querySelector("div") let timeout box.onclick = () => { box.classList.add("black") } box.ontransitionend = (e) => { // 仅处理background-color属性的过渡结束 if (e.propertyName !== 'background-color') return timeout = setTimeout(() => { box.classList.remove("black") }, 3000) } window.onkeydown = () => { clearTimeout(timeout) }
内容的提问来源于stack exchange,提问作者strjak
相关产品推荐
相关产品推荐

