animationend事件绑定异常排查:为何首个动画结束后即触发alert弹窗?
为什么alert在第一个动画结束后就触发了?
嗨,这个问题其实是**DOM事件冒泡(Event Bubbling)**在搞鬼!让我一步步给你捋清楚发生的全过程:
- 点击按钮后,你给
second元素添加了4秒的动画,动画结束时会触发second的animationend事件。 - 由于
second是one的子元素,按照DOM事件流的默认规则,这个animationend事件会向上冒泡,触发父元素one的animationend事件——哪怕这时候one还没开始动画! - 而你刚好是在
second的animationend回调里,才给one绑定了animationend监听函数。这时候冒泡上来的事件刚好命中这个刚绑定的函数,直接就弹出了alert,完全等不到one的动画完成。
解决方法有这几种,你可以选适合自己的:
方案一:判断事件源,确保是one自己的动画结束
在one的animationend回调里,检查触发事件的元素是不是one本身,只有符合条件才执行alert:
const overlay = document.getElementById('one'); const second = document.getElementById('second'); const mybtn = document.getElementById('mybtn'); mybtn.addEventListener('click', function(){ second.style.animation = '4000ms ease forwards test'; second.addEventListener("animationend", function() { overlay.style.animation = '4000ms ease forwards test'; overlay.addEventListener("animationend", function(e) { // 确认事件来自one元素本身,而非子元素冒泡 if(e.target === this){ alert('hello'); } }); }); });
方案二:使用once: true让监听函数仅执行一次
给事件监听添加once: true配置,这样函数只会触发一次,既避免冒泡干扰,也不用手动移除监听:
const overlay = document.getElementById('one'); const second = document.getElementById('second'); const mybtn = document.getElementById('mybtn'); mybtn.addEventListener('click', function(){ second.style.animation = '4000ms ease forwards test'; second.addEventListener("animationend", function() { overlay.style.animation = '4000ms ease forwards test'; overlay.addEventListener("animationend", function() { alert('hello'); }, { once: true }); // 仅执行一次 }, { once: true }); });
方案三:通过animationName判断对应动画
利用事件对象的animationName属性,确认是test动画结束时才触发alert,这样就算有其他动画也不会误触发:
const overlay = document.getElementById('one'); const second = document.getElementById('second'); const mybtn = document.getElementById('mybtn'); mybtn.addEventListener('click', function(){ second.style.animation = '4000ms ease forwards test'; second.addEventListener("animationend", function() { overlay.style.animation = '4000ms ease forwards test'; overlay.addEventListener("animationend", function(e) { if(e.animationName === 'test'){ alert('hello'); } }); }); });
简单来说,事件冒泡是DOM的默认行为,处理嵌套元素的同类事件时,一定要注意区分事件的真实来源,避免这种“提前触发”的坑~
内容的提问来源于stack exchange,提问作者Leith
相关产品推荐
相关产品推荐

