自定义通知系统setTimeout异常:仅最新通知执行反向动画
解决多通知触发时仅最新通知消失的问题
问题根源
使用innerHTML +=添加新通知时,浏览器会重新解析整个.notification-holder容器的内容,直接替换掉之前所有已存在的通知元素。这会导致旧通知上绑定的动画结束事件监听全部丢失,无法执行后续的反向动画和移除逻辑,只有最后创建的新通知能正常完成整个生命周期。
修复后的代码
JavaScript
var notificationCount = 0; // 提前创建并缓存通知容器 const notificationHolder = document.createElement('div'); notificationHolder.className = 'notification-holder'; document.body.appendChild(notificationHolder); function notification(content){ notificationCount += 1; // 创建单个通知元素 const notificationEl = document.createElement('div'); notificationEl.className = 'notification'; notificationEl.id = `notification-${notificationCount}`; notificationEl.innerHTML = `<p>${content}</p>`; notificationHolder.appendChild(notificationEl); // 执行入场动画 notificationEl.style.animation = "notificationAnimate 0.2s forwards"; notificationEl.addEventListener("animationend", () => { notificationEl.style.visibility = "visible"; notificationEl.style.animation = ""; setTimeout(() => { notificationEl.style.animation = "notificationAnimate 0.2s reverse"; // 监听退场动画结束,完成后移除元素,once确保事件只触发一次 notificationEl.addEventListener("animationend", () => { notificationEl.remove(); }, { once: true }); }, 1000); }, { once: true }); }
CSS(无需修改)
:root{ --black: #151515; --white: #EDEDEE; } .notification-holder{ position: absolute; bottom: 0px; right: 10px; padding-bottom: 10px; overflow: hidden; } .notification{ width: 250px; padding: 10px; text-align: center; background-color: var(--black); color: var(--white); font-size: 14px; font-family: "Poppins", sans-serif; border-radius: 10px; } .notification:not(:first-of-type){ margin-top: 10px; } @keyframes notificationAnimate{ 0%{ opacity: 0; max-height: 1px; transform: translateY(100px); scale: 0; } 100%{ opacity: 1; max-height: fit-content; transform: translateY(0px); /* visibility: visible; */ scale: 1; } }
HTML(无需修改)
<html> <head> </head> <body> <button onclick="notification('Dark theme has been enabled!')">Dark theme </button> </body> </html>
关键修改点
- 用
createElement+appendChild替代innerHTML +=,避免旧通知元素被重新渲染,保留原有事件监听 - 给
addEventListener添加{ once: true }选项,确保动画结束事件只触发一次,避免重复绑定和内存泄漏 - 提前创建并缓存通知容器,减少DOM查询次数,提升性能
内容的提问来源于stack exchange,提问作者The Myth
相关产品推荐
相关产品推荐

