Vue3中如何开启多个Bootstrap Toast实例而非覆盖旧实例
Bootstrap 5 多Toast实例不覆盖的原生实现(Vue3 + TypeScript)
问题出在你复用了同一个DOM节点创建Toast实例——每次调用showToast都是操作同一个#toastInfo元素,新实例显示时会替换掉旧的。要实现多Toast共存,需要每次创建新的Toast DOM元素,而不是复用同一个。
以下是Bootstrap原生的简便实现方案:
完整代码示例
<template> <!-- Toast容器,用Bootstrap定位类固定在右上角 --> <div ref="toastContainer" class="position-fixed top-0 end-0 p-3" style="z-index: 11"></div> <!-- 测试按钮 --> <button @click="showToast('提示', '这是第N条Toast消息')" class="btn btn-primary"> 弹出新Toast </button> </template> <script setup lang="ts"> import { ref } from 'vue' import { Toast } from 'bootstrap' // 引用Toast容器 const toastContainer = ref<HTMLDivElement | null>(null) // 生成唯一ID,避免元素冲突 let toastIdCounter = 0 function showToast(title: string, content: string) { // 1. 动态创建Toast DOM元素 const toastEl = document.createElement('div') toastEl.classList.add('toast') toastEl.setAttribute('role', 'alert') toastEl.setAttribute('aria-live', 'assertive') toastEl.setAttribute('aria-atomic', 'true') toastEl.id = `toast-${toastIdCounter++}` // 填充Toast内容 toastEl.innerHTML = ` <div class="toast-header"> <strong class="me-auto">${title}</strong> <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button> </div> <div class="toast-body"> ${content} </div> ` // 2. 将Toast添加到容器 if (toastContainer.value) { toastContainer.value.appendChild(toastEl) } // 3. 创建并显示Toast实例 const toastInstance = new Toast(toastEl, { animation: true, autohide: true, delay: 3000 }) toastInstance.show() // 4. Toast隐藏后自动清理DOM,避免冗余 toastEl.addEventListener('hidden.bs.toast', () => { toastEl.remove() }) } </script>
关键说明
- 动态创建DOM:每次调用
showToast都生成全新的.toast元素,确保每个Toast实例独立存在。 - 容器定位:用Bootstrap内置的
position-fixed top-0 end-0类把Toast固定在右上角,z-index:11保证Toast在页面其他内容之上显示。 - 自动清理:监听
hidden.bs.toast事件,Toast关闭后自动从DOM中移除,避免内存占用和无效DOM堆积。 - 可扩展定制:可以给
showToast函数添加更多参数(比如自定义延迟时间、背景色、显示位置等),适配不同业务场景。
内容的提问来源于stack exchange,提问作者Azael
相关产品推荐
相关产品推荐

