Bootstrap模态框关闭控制:校验(含AJAX)通过才允许关闭,preventDefault后无法取消求解
原有代码的核心问题
- 事件绑定逻辑错误:把保存按钮的
click事件绑定写在hide.bs.modal的回调里,每次模态框触发隐藏时都会重复绑定点击事件,且hide事件触发时点击事件早已执行完毕,根本拿不到最新的校验状态 - 变量逻辑写反:AJAX提交成功后你把
cancel设为了true,反而会阻止模态框关闭,和你要的效果完全相反 - 同步AJAX会阻塞浏览器,体验很差,不符合前端开发最佳实践
正确实现方案
实现思路:
- 单独给保存按钮绑定点击事件,所有表单校验、AJAX提交逻辑都在点击事件内完成
- 新增一个全局标记位
allowClose,用来标识当前是不是校验通过的合法关闭操作 - 只有
allowClose为true的时候才允许模态框关闭,否则拦截hide事件
修正后代码:
// 全局标记位,标识是否允许关闭模态框 let allowClose = false; // 拦截模态框关闭事件 $('#modalAltaReceta').on('hide.bs.modal', function(e){ // 只有标记位为true时才允许关闭 if(!allowClose) { e.preventDefault(); e.stopImmediatePropagation(); return false; } }); // 保存按钮点击逻辑,单独绑定,不要写在hide事件里 $("#grabarReceta").click(function() { let cancel = false; // 基础表单校验 if($("#inputNombreReceta").val().trim()=="") { alert("请输入食谱名称"); cancel = true; } else if($("#inputIntroReceta").val().trim()=="") { alert("请输入简短介绍"); cancel = true; } else if($("#inputInstruccionesReceta").val().trim()=="") { alert("请填写食谱制作步骤"); cancel = true; } let cantidadSinIngreso = 0; $(".inputIngredientes").each(function(index, item) { if(item.value.trim() == "") cantidadSinIngreso++ }); if(cantidadSinIngreso > 0) { cancel = true; alert("请至少填写一种食材"); } // 基础校验不通过直接终止 if(cancel) return; // 校验通过提交AJAX $.ajax({ url: 'php/recetas.php', async: true, type: 'POST', dataType: 'json', data: "tipo_id=grabarReceta&" + $("#frm_nueva_receta").serialize(), success: function(data) { if(data['msg'] == 'ok') { // 提交成功,把允许关闭的标记位设为true allowClose = true; // 手动调用关闭模态框,这时候因为标记位是true,不会被拦截 $('#modalAltaReceta').modal('hide'); // 重置标记位,避免下次打开模态框时直接放行关闭 setTimeout(()=> allowClose = false, 300); alert("保存成功"); } else { alert("提交失败:" + data.msg); } }, error: function() { alert("网络请求失败,请重试"); } }); });
如果你不需要拦截用户点击模态框右上角关闭按钮、点击模态框外空白区域的关闭操作,只需要控制点击保存按钮时的关闭逻辑,甚至可以去掉
hide.bs.modal的拦截逻辑,直接在AJAX成功后调用$('#modalAltaReceta').modal('hide')即可,逻辑更简洁。
内容的提问来源于stack exchange,提问作者pablo Fiscella
相关产品推荐
相关产品推荐

