Bootstrap5 alert表单提交成功后仅首次触发显示的问题排查
问题根因
这是Bootstrap5 Alert组件的默认行为导致的:给关闭按钮加data-bs-dismiss="alert"属性后,点击关闭时组件会直接把整个alert元素从DOM树中彻底删除,而非单纯隐藏元素:
- 首次提交成功时,你通过
classList.toggle('d-none')移除隐藏类,alert正常显示 - 点击关闭按钮后,Bootstrap直接删除了整个alert节点
- 你代码开头提前缓存的
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
相关产品推荐
相关产品推荐

