自定义Toast组件重复显示问题排查求助
问题描述
我编写了一个用于创建和显示Toast弹窗的类,弹窗的显示时长与内容通过类方法传入并控制。触发Toast后,它会在设定时长后正常隐藏,但随后会再次显示并很快隐藏,而代码中并未重复调用弹窗方法。
疑问:
我猜测这可能与上下文或定时器有关,但缺乏相关经验,能否帮忙解决?提前感谢!Max
代码实现
JavaScript
class ToastHawaii { constructor(config = {}) { this.duration = typeof(config.duration) == 'undefined' ? 1000 : config.duration; this.toastContainer = config.toastContainer; this.timer = null; // 存储定时器ID,用于后续清除 } makeToast(d) { const html = `<div class="toast"> <div>${d.title}</div> <div class="right">${d.content}</div> </div>`; // 清除之前的定时器,避免多次点击导致状态混乱 if (this.timer) clearTimeout(this.timer); this.toastContainer.innerHTML = html; // 先移除show类再强制重绘,确保过渡动画能重新触发 this.toastContainer.classList.remove("show"); void this.toastContainer.offsetWidth; this.toastContainer.classList.add("show"); this.timer = setTimeout(() => { this.toastContainer.classList.remove("show"); }, this.duration); } } const mA = new ToastHawaii({ duration: 4000, toastContainer: document.querySelector('#myAlertContainer') }); const content = `ICON`; document.querySelector("button").addEventListener('click', () => { mA.makeToast({ title: "hello", content: content }); })
CSS
#myAlertContainer { position: fixed; left: 0%; top: 0; visibility: hidden; opacity: 0; width:100%; z-index: 1; height:60px; /* 用CSS过渡替代关键帧动画,状态切换更可控 */ transition: visibility 0s 0.5s, opacity 0.5s, top 0.5s; } .toast { box-sizing: border-box; display: flex; justify-content: space-between; align-items: center; border-radius: 8px; background: gray; color: #000; height:100%; padding: 0 16px; font-size: 0.8rem; font-weight: bold; margin: 0 auto; max-width: 350px; } .right { display: flex; gap: 5px; align-items: center; } #myAlertContainer.show { visibility: visible; opacity: 1; top: 30px; transition: opacity 0.5s, top 0.5s; }
HTML
<div id="myAlertContainer"></div> <button>makeAlert!</button> <h1>hello</h1> <p>lorem ipsum</p>
问题原因及解决说明
- 动画与定时器逻辑冲突:原CSS中
fadeout动画设置为2.5秒后触发,而JS定时器是4秒后移除show类,两者时间不匹配,导致动画未完成就切换状态,加上未保持动画结束后的元素状态,最终出现弹窗闪现。 - 重复点击的定时器叠加:多次点击按钮时,之前的定时器未被清除,多个移除
show类的操作叠加,造成弹窗状态混乱。 - 动画触发机制问题:直接重复添加
show类不会重新触发关键帧动画,需要先移除类并强制重绘。
解决时改用CSS过渡替代关键帧动画,让状态切换更可控;每次调用makeToast时清除之前的定时器;通过强制重绘确保每次点击都能重新触发过渡效果,彻底解决弹窗闪现问题。
内容的提问来源于stack exchange,提问作者Max Pattern
相关产品推荐
相关产品推荐

