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

Bootstrap5 alert表单提交成功后仅首次触发显示的问题排查

问题根因

这是Bootstrap5 Alert组件的默认行为导致的:给关闭按钮加data-bs-dismiss="alert"属性后,点击关闭时组件会直接把整个alert元素从DOM树中彻底删除,而非单纯隐藏元素:

  1. 首次提交成功时,你通过classList.toggle('d-none')移除隐藏类,alert正常显示
  2. 点击关闭按钮后,Bootstrap直接删除了整个alert节点
  3. 你代码开头提前缓存的myAlert变量,指向的是已经被删掉的废弃DOM节点,后续提交时操作这个不存在的节点不会产生任何效果,自然无法再次弹出提示。

另外你用toggle切换类的写法本身也有逻辑漏洞:如果用户没有手动关闭alert,再次提交时toggle反而会给alert加上d-none把它藏起来,显示状态完全不可控。

修复方案

不要用Bootstrap默认的删除DOM的关闭逻辑,手动控制alert的显示隐藏,保证元素始终留在DOM中即可。

1. 调整HTML结构

去掉关闭按钮上的data-bs-dismiss="alert"属性,阻断Bootstrap自动删DOM的逻辑,初始状态保留d-none隐藏即可:

<div class="alert my-alert alert-warning alert-dismissible fade d-none" role="alert">
  <strong>Thank you!</strong> We have received your message.
  <button type="button" class="btn-close" aria-label="Close"></button>
</div>

2. 重写JS交互逻辑

  • 放弃提前缓存alert元素的写法,要么每次提交时重新获取元素,要么保证元素不被删除就可以长期持有引用
  • 弃用toggle切换类,显示/隐藏时明确添加/移除对应的类,避免状态错乱
  • 单独给关闭按钮绑定事件,点击时只做隐藏处理,不删除DOM
  • 可选增加自动消失逻辑,优化使用体验
const scriptURL = 'https://script.google.com/macros/......'
const form = document.forms['portofolio-contact-form']
const btnKirim = document.querySelector('.my-btn')
const btnLoading = document.querySelector('.btn-loading')

// 手动处理alert关闭逻辑:仅隐藏,不删除DOM
document.addEventListener('click', e => {
  if (e.target.matches('.alert .btn-close')) {
    const alertBox = e.target.closest('.alert')
    alertBox.classList.add('d-none')
    alertBox.classList.remove('show')
  }
})

form.addEventListener('submit', e => {
  e.preventDefault()
  const myAlert = document.querySelector('.my-alert')
  // 切换加载状态
  btnLoading.classList.remove('d-none')
  btnKirim.classList.add('d-none')

  fetch(scriptURL, { method: 'POST', body: new FormData(form) })
    .then(response => {
      // 恢复按钮状态
      btnLoading.classList.add('d-none')
      btnKirim.classList.remove('d-none')
      // 明确显示提示框
      myAlert.classList.remove('d-none')
      // 加show类触发Bootstrap自带的淡入动画
      myAlert.classList.add('show')
      form.reset()
      // 可选:3秒后自动隐藏提示框
      setTimeout(() => {
        myAlert.classList.add('d-none')
        myAlert.classList.remove('show')
      }, 3000)
      console.log('Success!', response)
    })
    .catch(error => console.error('Error!', error.message))
})

这种写法不需要反复创建/删除DOM节点,性能更好,逻辑也完全可控,不管提交多少次、关闭多少次提示框,都能正常弹出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 12:54:16