jQuery实现表单未保存离开时弹出自定义确认弹窗功能
jQuery表单未保存离开二次确认实现方案
原有代码问题梳理
- 表单变更监听不全:select下拉选择、文件输入框的修改没有被监听,富文本textarea选择器漏写类前缀
.,dropzone仅监听点击事件无法准确识别文件上传变更 - 提交保存逻辑未做标记重置:点击保存按钮触发表单提交时,没有重置修改状态,会误弹出确认框
- 事件逻辑不兼容浏览器规则:原生
beforeunload事件受浏览器安全限制,无法直接唤起自定义模态框,需要配合页面内跳转拦截才能实现自定义弹窗效果 - 模态框交互缺失:关闭、留在页面、离开页面三个操作没有绑定对应事件,无法正常交互
调整后完整代码
1. 自定义模态框微调(去掉硬编码跳转地址)
<div id="openModal" class="modalDialog" style="display: none;"> <div> <a href="javascript:;" title="Close" class="close modal-stay">X</a> <h2>确定要离开当前页面吗?</h2> <p>您修改的内容尚未保存,离开后将丢失所有更改</p> </div> <a href="javascript:;" class="modal-leave">离开页面</a> <a href="javascript:;" class="modal-stay">留在页面</a> </div>
2. jQuery逻辑代码
$(document).ready(function(){ // 初始化修改标记、存储待跳转地址 let isChanged = false; let pendingTarget = ''; // 记录表单初始值,用于后续比对是否真的修改 const $allFormFields = $('form input, form select, form textarea, .dropzone'); const initialValues = {}; $allFormFields.each(function(index){ const fieldKey = `field_${index}`; initialValues[fieldKey] = $(this).val(); $(this).data('fieldKey', fieldKey); }); // 监听所有表单变更事件 // 普通输入框、下拉选择、文本域变更 $('form').on('input change', 'input, select, textarea', function(){ const key = $(this).data('fieldKey'); if($(this).val() !== initialValues[key]){ isChanged = true; } else { // 检查是否所有字段都回到初始值,重置标记 checkAllFieldReset(); } }); // 富文本编辑器内容变更(兼容富文本自动同步到textarea的场景) $('.rich_textarea').on('input propertychange paste', function() { const key = $(this).data('fieldKey'); if($(this).val() !== initialValues[key]){ isChanged = true; } }); // Dropzone文件上传变更监听(替换原来的click监听,避免误判) if(window.Dropzone){ Dropzone.forElement("#dropzone").on("addedfile removedfile", function() { isChanged = true; }); } // 保存按钮点击时重置修改标记,提交表单不弹提示 $('input[type="submit"]').on('click', function(){ isChanged = false; }); // 拦截页面内所有跳转链接 $(document).on('click', 'a[href]', function(e){ const href = $(this).attr('href'); // 排除javascript:void(0)、锚点跳转这类不离开当前页的链接 if(href.startsWith('javascript:') || href.startsWith('#')) return; if(isChanged){ e.preventDefault(); pendingTarget = href; $('#openModal').show(); } }); // 监听页面关闭/刷新/前进后退事件,弹出浏览器原生提示(自定义模态框无法在这个场景唤起,是浏览器安全限制) window.onbeforeunload = function(e){ if(isChanged){ e.preventDefault(); e.returnValue = '您修改的内容尚未保存,确定要离开吗?'; return e.returnValue; } }; // 模态框交互逻辑 // 留在页面/关闭弹窗 $('.modal-stay').on('click', function(){ pendingTarget = ''; $('#openModal').hide(); }); // 离开页面 $('.modal-leave').on('click', function(){ isChanged = false; $('#openModal').hide(); window.location.href = pendingTarget; }); // 工具方法:检查所有字段是否回到初始值 function checkAllFieldReset(){ let allReset = true; $allFormFields.each(function(index){ const key = $(this).data('fieldKey'); if($(this).val() !== initialValues[key]){ allReset = false; return false; } }); isChanged = !allReset; } });
实现说明
- 点击保存按钮提交表单时,会自动重置修改状态,不会触发任何离开提示
- 页面内点击链接跳转时,若有未保存修改会直接弹出自定义模态框,支持选择离开或留下
- 刷新页面、关闭标签页、点击浏览器前进/后退按钮时,受浏览器安全限制无法展示自定义模态框,会弹出浏览器统一的确认提示,避免自定义代码被恶意站点滥用
- 只有当表单内容和初始值不一致时才会标记为已修改,用户修改后又改回原值不会触发提示
- Dropzone监听真实的文件增删事件,不会因为误点上传区域就触发未保存提示
注意:如果你的富文本编辑器是独立封装的(比如TinyMCE、CKEditor),需要额外给编辑器绑定内容变更事件同步标记状态,避免富文本内容修改无法被识别。
内容的提问来源于stack exchange,提问作者flytomoon777
相关产品推荐
相关产品推荐

