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

Vue2中如何实现可重置倒计时的自动关闭<b-alert>?

Vue2 可重置倒计时的实现方案

核心思路

将每个通知的状态(消息内容、剩余倒计时、定时器)独立维护,用数组存储所有活跃通知,针对相同消息做倒计时重置,不同消息新增通知实例,彻底避免定时器冲突问题。

具体实现代码

1. EventBus 定义

// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()

2. 通知组件代码

<template>
  <div class="notification-container">
    <b-alert
      v-for="notification in notifications"
      :key="notification.id"
      :show="true"
      :variant="notification.variant || 'info'"
      dismissible
      @dismissed="removeNotification(notification.id)"
    >
      {{ notification.message }}
      <small class="ml-2">剩余 {{ notification.remainingTime }} 秒关闭</small>
    </b-alert>
  </div>
</template>

<script>
import { EventBus } from './event-bus'

export default {
  data() {
    return {
      notifications: []
    }
  },
  created() {
    EventBus.$on('show-notification', (payload) => {
      const { message, variant = 'info' } = payload
      this.handleNotification(message, variant)
    })
  },
  beforeDestroy() {
    this.notifications.forEach(notify => {
      clearInterval(notify.timerId)
    })
    EventBus.$off('show-notification')
  },
  methods: {
    handleNotification(message, variant) {
      const existingNotify = this.notifications.find(n => n.message === message)
      
      if (existingNotify) {
        clearInterval(existingNotify.timerId)
        existingNotify.remainingTime = 6
        existingNotify.timerId = this.startCountdown(existingNotify.id)
      } else {
        const newNotify = {
          id: Date.now() + Math.random(),
          message,
          variant,
          remainingTime: 6,
          timerId: null
        }
        newNotify.timerId = this.startCountdown(newNotify.id)
        this.notifications.push(newNotify)
      }
    },
    startCountdown(notifyId) {
      return setInterval(() => {
        const notify = this.notifications.find(n => n.id === notifyId)
        if (notify) {
          notify.remainingTime--
          if (notify.remainingTime <= 0) {
            this.removeNotification(notifyId)
          }
        }
      }, 1000)
    },
    removeNotification(notifyId) {
      const notifyIndex = this.notifications.findIndex(n => n.id === notifyId)
      if (notifyIndex !== -1) {
        clearInterval(this.notifications[notifyIndex].timerId)
        this.notifications.splice(notifyIndex, 1)
      }
    }
  }
}
</script>

<style scoped>
.notification-container {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 9999;
  width: 350px;
}
.b-alert {
  margin-bottom: 10px;
}
</style>

3. 使用方式(其他组件中触发通知)

// 在任意组件中
import { EventBus } from './event-bus'

// 触发普通通知
EventBus.$emit('show-notification', {
  message: '操作成功!',
  variant: 'success'
})

// 触发相同消息的通知(会重置倒计时)
EventBus.$emit('show-notification', {
  message: '操作成功!'
})

关键修复点(针对你的问题)

  1. 独立定时器:每个通知拥有专属定时器,重置时先清除旧定时器再启动新的,避免多个定时器同时修改同一个倒计时变量,解决bannerCountDown频繁调用的问题。
  2. 状态隔离:用数组存储每个通知的独立状态,相同消息只修改已有项的倒计时,不同消息新增项,满足多通知显示需求。
  3. 内存泄漏防护:组件销毁时清除所有定时器并解绑事件监听,通知关闭时也清除对应定时器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:15:34