查看 html 表单是不是已更改

Posted

技术标签:

【中文标题】查看 html 表单是不是已更改【英文标题】:Find out if html form has changed查看 html 表单是否已更改 【发布时间】:2012-05-05 21:38:09 【问题描述】:

使用 jquery,我向表单添加了一个更改处理程序。 这在任何输入更改时有效,但仅在用户手动更改输入时才有效,而不是在其他代码更改输入时。

是否有任何方法可以检测表单是否已更改,即使其输入已被代码更改?

【问题讨论】:

【参考方案1】:

是的,这似乎有些混乱。在理想的世界中,您会期望在输入发生变化时发生 onchange 事件,但事实并非如此。我肯定有充分的理由 - 也许不是。

我克服这个障碍的一种方法是在显示表单状态之后将其捕获到变量中,然后在提交之前检查状态是否已更改并采取相应措施。

序列化函数返回的状态是一个易于存储的状态。存储状态的一个简单地方是使用数据功能。 serialize 和 data 都可用于 jquery。

当然,您可以使用其他不同形式的状态(某种形式的哈希)或存储该状态(例如标准全局变量)。

这是一些原型代码:

如果您的表单 id 是“xform”,那么您可以在表单显示后调用以下代码:

$('#xform').data('serialize',$('#xform').serialize());

然后,当您需要检查时,例如在按钮提交之前,您可以使用:

if($('#xform').serialize()!=$('#xform').data('serialize'))
    // Form has changed!!!

您可以将所有这些打包到一个复制和粘贴 javascript sn-p 中,这将为您提供一个 formHasChanged() 函数,以便在您需要的任何地方调用它(未测试):

$(function() 
    $('#xform').data('serialize',$('#xform').serialize());
);
function formHasChanged()
    if($('#xform').serialize()!=$('#xform').data('serialize'))
        return(true);
    
    return(false);

但我会停在这里,否则我将创建另一个 jquery 插件。

【讨论】:

它在很多情况下都有效,但我的情况是,我有几个字段在某些情况下被禁用,当它发生时,它们不在表单的序列化值中当没有变化时,系统在比较两个字符串时检测到变化。要在这种情况下工作,您必须确保在获取序列化函数的结果之前设置控件状态。无论如何,这是一个非常好的解决方案! :) +1 这个解决方案***.com/questions/959670/… 在我看来要好得多,因为它可以处理禁用字段。 在 2018 年及以后避免使用 jQuery。可以在下面的答案中找到一种独立于哈希/序列化函数的性能更高的算法。 @AnthumChris 好吧,有些人可能会就此与您争论,但我当然感谢您的反对票。【参考方案2】:

序列化表单当然是一种选择,但如果出现以下情况,它将不起作用:

您想知道哪些字段发生了变化 它只需要检查字段的子集 动态添加或删除字段。

幸运的是,每个表单元素都有一个与其对象关联的默认值:

输入,文本区域:默认值 复选框,单选:defaultChecked 选择:默认选择

例如:检查输入或文本区域是否已更改:

var changed = false;
$(":text,textarea").each(function()
    changed = this.value != this.defaultValue;
    return !changed; // return if at least one control has changed value
);

【讨论】:

defaultValue 属性似乎已过时:link【参考方案3】:

这很容易在没有 jQuery 的 JavaScript 中实现。 initChangeDetection()可以多次调用:

function initChangeDetection(form) 
  Array.from(form).forEach(el => el.dataset.origValue = el.value);

function formHasChanges(form) 
  return Array.from(form).some(el => 'origValue' in el.dataset && el.dataset.origValue !== el.value);

Test on JS Bin


对于不支持新箭头/数组函数的旧浏览器:
function initChangeDetection(form) 
  for (var i=0; i<form.length; i++) 
    var el = form[i];
    el.dataset.origValue = el.value;
  

function formHasChanges(form) 
  for (var i=0; i<form.length; i++) 
    var el = form[i];
    if ('origValue' in el.dataset && el.dataset.origValue !== el.value) 
      return true;
    
  
  return false;

【讨论】:

超级棒!谢谢谢谢 .value 不会告诉您 checkboxradio 输入是否已更改。在这些情况下,它需要使用.checked【参考方案4】:

不是以常规方式。

您可以通过输入进行更改,然后触发更改事件。

$('#inputId').val('foo').trigger('change');

或者用这个:

$('#inputId').val('foo').change();

【讨论】:

+1 以获得很好的答案。但是谁投了反对票,我认为他/她根本不知道trigger('change')change() @thecodeparadox。太多傻瓜有键盘和鼠标... :) 但他们不知道在哪里使用它们 我没有投反对票,但我认为 DOMAttrModified 不会在输入字段的值被任何更改时触发; value 是一个属性,而不是一个 DOM 节点...***.com/a/147011/295783 - OP 也想知道是否有某些东西改变了输入,这可能是一个扫描仪之类的,这意味着他没有在任何地方编写更改脚本 @mplungjan。我后来添加了突变事件。无论如何,你是对的,我正在删除那部分。【参考方案5】:

这就是我所做的(我使用 zaf 的答案找到了我的解决方案)

$("form").change(function() 
    $(this).data("changed","true");
);

$("input[type='submit']").click(function() 
    if($("form").data("changed") == "true") 
        var discard = confirm("Some unsaved changes. Discard them ?");
        if(!discard) return false;
    
);

【讨论】:

你可以返回return confirm("...");,但我认为这样阅读会更难【参考方案6】:

试试onchange属性 根据W3c,它应该在元素内容、选择或选中状态发生变化时触发。

【讨论】:

不正确,它不适用于 code 更改。哦,更改处理程序就像 onchange 属性一样,但将关注点分开。 @gdoron jQuery.trigger() 或 jQuery.change() 使用什么 javaScript 来检测代码更改? 它不只是触发 onchange 处理程序。

以上是关于查看 html 表单是不是已更改的主要内容,如果未能解决你的问题,请参考以下文章

如果主表单已更改/弄脏,是不是可以要求子表单?

有没有办法在提交之前检查表单以查看是不是已选中任何复选框?

提交表单返回的是 application/json 而不是 text/html

我如何知道表单输入已更改?

在 iOS 上查看时,是不是可以在使用 UIDatePickerView 的 Web 表单中使用 HTML?

Microsoft Access 子表单定义已更改