Vue.js集成Bootstrap5时myModal.hide()方法不生效问题求助
问题根因
出现这个问题是三个因素共同导致的:
- 每次执行关闭逻辑时都重新
new Modal()创建实例,没有复用模态框初始化后的真实实例,回车触发场景下新创建的实例无法匹配当前处于激活状态的模态框 - 回车事件没有阻止默认行为,加上输入框上冗余的
data-bs-target属性,会触发浏览器和Bootstrap的默认事件逻辑,干扰模态框状态 - 调用
hide()方法后立刻执行路由跳转,模态框对应的DOM还没完成关闭逻辑就被路由卸载,导致遮罩层、模态框状态残留,无法正常隐藏
修复方案
按以下步骤调整即可解决:
- 清理模板冗余属性:删除密码输入框上的
data-bs-target="#login"属性,该属性仅用于绑定触发模态框弹出的按钮元素,放在输入框上无实际作用还会干扰事件逻辑 - 提前初始化模态框实例,不要在关闭时重复创建:
在Vue组件的选项中提前声明实例存储变量,在组件挂载完成后完成模态框初始化,后续所有显示/隐藏操作都复用这个实例export default { data() { return { // 其他原有变量(email、password等) loginModal: null, } }, mounted() { // 提前初始化登录模态框实例 this.loginModal = new Modal(document.getElementById('login')) }, methods: { login(e) { // 阻止回车默认事件冒泡 e?.preventDefault?.() const auth = getAuth(); signInWithEmailAndPassword(auth, this.email, this.password) .then((userCredential) => { // 复用提前初始化的实例调用hide,不要重新new this.loginModal.hide(); // 加短延时等待模态框关闭逻辑执行完成,再做弹窗和路由跳转,避免DOM提前卸载 setTimeout(() => { Swal.fire({ position: "center", icon: "success", title: "登入成功", showConfirmButton: false, timer: 1500, }); this.$router.replace("admin"); }, 200) }) .catch((error) => { const errorCode = error.code; if (errorCode === "auth/wrong-password") { Swal.fire({ position: "center", icon: "error", title: "密碼錯誤", showConfirmButton: false, timer: 2000, }); } else { Swal.fire({ position: "center", icon: "error", title: "密碼錯誤或信箱尚未註冊", showConfirmButton: false, timer: 2000, }); } console.log(error); }); } } } - 给回车事件加阻止默认行为修饰符(可选,和方法内的事件拦截二选一即可):将模板内的事件绑定从
@keyup.enter="login"改为@keyup.enter.prevent="login",从模板层拦截默认事件 - 增加兜底逻辑:如果路由跳转后仍残留黑色遮罩层,可以在admin页面的挂载钩子中添加清理逻辑,手动移除残留元素和body上的模态框标记类
// admin页面mounted钩子中添加 document.body.classList.remove('modal-open') document.querySelectorAll('.modal-backdrop').forEach(el => el.remove()) document.body.style.removeProperty('padding-right')
内容的提问来源于stack exchange,提问作者Albert Hsu
相关产品推荐
相关产品推荐

