DirtyForms与$.blockUI兼容异常:取消确认后页面被阻塞
解决DirtyForms与blockUI冲突:取消确认后页面卡住的问题
我完全懂你遇到的糟心情况——表单改了内容没保存,点链接时DirtyForms弹出确认框,结果不管用户点确认还是取消,blockUI都会直接执行,取消后页面就僵住了。这是因为你在链接的click事件里直接调用了$.blockUI(),而DirtyForms的确认流程是在这个点击事件之后才触发的,等于blockUI已经先生效了,取消也没法恢复页面。
正确解决方案:精准控制blockUI的执行时机
我们要把blockUI的调用延迟到用户明确确认要离开页面时才执行,而不是一点链接就触发。可以通过DirtyForms提供的确认回调函数来实现:
$(function() { // 初始化DirtyForms $('form[method="post"]').dirtyForms(); // 处理所有链接的点击事件 $('a').on('click', function(e) { const $targetLink = $(this); const targetHref = $targetLink.attr('href'); // 先阻止默认跳转,把控制权交给DirtyForms e.preventDefault(); // 检查表单是否处于"未保存修改"的脏状态 if ($.DirtyForms.isDirty()) { // 触发DirtyForms的确认弹窗流程 $.DirtyForms.confirm({ // 用户点击"确认离开"时执行 proceed: function() { $.blockUI(); // 手动跳转到目标链接 window.location.href = targetHref; }, // 用户点击"取消"时执行 stay: function() { // 啥也不做,保持当前页面正常状态 return false; } }); } else { // 表单没修改过,直接执行blockUI并跳转 $.blockUI(); window.location.href = targetHref; } }); });
为什么这个方案能解决问题?
- 先阻止了链接的默认跳转行为,避免页面直接跳转,把流程交给DirtyForms处理
- 只有用户明确确认要离开时,才会调用
$.blockUI()并执行跳转;如果用户选择取消,不会触发任何block操作,页面完全正常 - 对于未修改的表单,依然保留原有体验:直接blockUI并跳转
关于你尝试过的事件的补充说明
stay.dirtyforms事件无效:大概率是因为你没把事件绑定到document上,正确写法是$(document).on('stay.dirtyforms', function() { $.unblockUI(); }),不过上面的回调方式更直接,不需要额外绑定事件defer.dirtyforms触发两次:通常是事件重复绑定或者DirtyForms内部机制导致的,用confirm回调的方式可以完全避免这个问题
完整可测试代码
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.dirtyforms/2.0.0/jquery.dirtyforms.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.blockUI/2.70/jquery.blockUI.min.js"></script> <p>Change the field content to activate DirtyForms, then click on the link.<br> When the popup appears, click on "cancel" to stay on the page.<br> Now blockUI won't fire if you choose to stay!</p> <form action="#" method="post"> <input type="text" name="username" required> <button type="submit">send</button> </form> <a href="https://google.com">click me after changing field content</a> <script> $(function() { $('form[method="post"]').dirtyForms(); $('a').on('click', function(e) { const $targetLink = $(this); const targetHref = $targetLink.attr('href'); e.preventDefault(); if ($.DirtyForms.isDirty()) { $.DirtyForms.confirm({ proceed: function() { $.blockUI(); window.location.href = targetHref; }, stay: function() { return false; } }); } else { $.blockUI(); window.location.href = targetHref; } }); }); </script>
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

