You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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>

问题原因及解决说明
  1. 动画与定时器逻辑冲突:原CSS中fadeout动画设置为2.5秒后触发,而JS定时器是4秒后移除show类,两者时间不匹配,导致动画未完成就切换状态,加上未保持动画结束后的元素状态,最终出现弹窗闪现。
  2. 重复点击的定时器叠加:多次点击按钮时,之前的定时器未被清除,多个移除show类的操作叠加,造成弹窗状态混乱。
  3. 动画触发机制问题:直接重复添加show类不会重新触发关键帧动画,需要先移除类并强制重绘。

解决时改用CSS过渡替代关键帧动画,让状态切换更可控;每次调用makeToast时清除之前的定时器;通过强制重绘确保每次点击都能重新触发过渡效果,彻底解决弹窗闪现问题。

内容的提问来源于stack exchange,提问作者Max Pattern

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:40:49