2018 年查看项目共通处理时,我发现:表单改动过,用户再执行某个按钮操作,才出现确认提示。本以为需要逐个给输入框绑监听,实际关键只有几行——在 form 上监听 change,再加一个类名标记。
子控件的 change 可以到达表单
在 DOM 就绪且已有 jQuery 的页面中:
$(function () {
$("#profileForm").on("change.dirtyMarker", function () {
$(this).addClass("form-changed");
});
});
事件从相关控件传到表单,因此无需为每个已存在的输入框复制相同逻辑。使用 on 的写法要求 jQuery 1.7 及以上;.dirtyMarker 是事件命名空间,便于只管理这一组监听。jQuery on
这记录的是收到 change 事件,不是对全部字段做实时比较。文本输入的 change 与每个按键的 input 事件也不等价。
怎样使用这个标记
例如,对一个明确为 type=button 的后续操作,可以先判断是否需要确认:
$("#continueButton").on("click.dirtyMarker", function () {
var changed = $("#profileForm").hasClass("form-changed");
if (changed && !window.confirm("表单发生过变更,仍要继续吗?")) {
return;
}
console.log("允许进入后续操作");
});
这是使用标记的交互示例,未包含保存接口或离开页面的全套逻辑。真正的业务动作应放在用户确认之后,不能先发请求再询问。
改回原值,标记仍然可能存在
这个标记只增不减。用户输入后又改回初值,仍可能带着 form-changed;因此它适合表达“发生过变更事件”,不是严格的“当前存在未保存内容”。
如果需要精确脏数据判断,应在加载完成时保存一个规范化基线,与当前业务字段比较。多选顺序、空白、数字格式、禁用控件、文件和富文本都需明确规则;不能只用一次表单序列化就假设覆盖所有状态。
保存、重置和程序赋值各有边界
- 只有保存被服务端确认成功后,才能更新基线并清除相应标记。
- 若保存期间用户继续编辑,不能无条件清掉这些较新的改动。
- 表单 reset 或重新加载数据后,应在实际值恢复完成时同步标记/基线,而不是仅观察重置按钮被点击。
- 程序调用 val 设置值通常不会自动触发 change;需要事件通知时要显式安排,并防止重复业务副作用。jQuery val
先明确需求是“曾改动”还是“当前偏离初始内容”,再选择事件标记或状态比较。两者不是同一个算法。