【问题标题】:Intercept a form submit in JavaScript and prevent normal submission在 JavaScript 中拦截表单提交并阻止正常提交
【发布时间】:2011-07-20 01:47:19
【问题描述】:

似乎有很多关于如何使用 javascript 提交表单的信息,但我正在寻找一种解决方案来捕获何时提交表单并在 javascript 中拦截它。

HTML

<form>
 <input type="text" name="in" value="some data" />
 <button type="submit">Go</button>
</form>

当用户按下提交按钮时,我确实希望提交表单,而是希望调用 JavaScript 函数。

function captureForm() {
 // do some stuff with the values in the form
 // stop form from being submitted
}

一个快速的技巧是向按钮添加一个 onclick 功能,但我不喜欢这个解决方案......有很多方法可以提交表单......例如在输入时按回车键,这不考虑。

【问题讨论】:

标签: javascript html forms


【解决方案1】:
<form id="my-form">
    <input type="text" name="in" value="some data" />
    <button type="submit">Go</button>
</form>

在 JS 中:

function processForm(e) {
    if (e.preventDefault) e.preventDefault();

    /* do what you want with the form */

    // You must return false to prevent the default form behavior
    return false;
}

var form = document.getElementById('my-form');
if (form.attachEvent) {
    form.attachEvent("submit", processForm);
} else {
    form.addEventListener("submit", processForm);
}

编辑:在我看来,这种方法比在表单上设置onSubmit 属性更好,因为它保持了标记和功能的分离。但这只是我的两分钱。

Edit2:更新了我的示例以包含 preventDefault()

【讨论】:

  • 就我使用jsbin.com/ejoyas 所见,这也不适用于 chrome
  • 请注意,附加事件代码需要在 dom 中的表单可用之后执行。例如使用window.onload=function() { ... } 包装它
  • processform() 函数什么时候被调用先生?
  • 不确定因为我不使用IE,但我认为attachEvent参数应该是“onsubmit”。
  • 这在 chrome 46 中不起作用,附加事件时出错,需要先加载页面
【解决方案2】:

您不能在附加事件的元素加载之前附加事件

这行得通-

纯 JS

DEMO

推荐使用事件监听器

// Should only be triggered on first page load
console.log('ho');

window.addEventListener("load", function() {
  document.getElementById('my-form').addEventListener("submit", function(e) {
    e.preventDefault(); // before the code
    /* do what you want with the form */

    // Should be triggered on form submit
    console.log('hi');
  })
});
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

但如果您不需要多个监听器,您可以使用 onload 和 onsubmit

// Should only be triggered on first page load
console.log('ho');

window.onload = function() {
  document.getElementById('my-form').onsubmit = function() {
    /* do what you want with the form */

    // Should be triggered on form submit
    console.log('hi');
    // You must return false to prevent the default form behavior
    return false;
  }
}
    <form id="my-form">
      <input type="text" name="in" value="some data" />
      <button type="submit">Go</button>
    </form>

jQuery

// Should only be triggered on first page load
console.log('ho');

$(function() {
  $('#my-form').on("submit", function(e) {
    e.preventDefault(); // cancel the actual submit

    /* do what you want with the form */

    // Should be triggered on form submit

    console.log('hi');
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="my-form">
  <input type="text" name="in" value="some data" />
  <button type="submit">Go</button>
</form>

【讨论】:

  • 我想你的意思是:$('#my-form).on('submit', function() { alert('hi'); });
  • @Michiel 虽然您提供的是与 jQuery 一起使用的东西,但提供的这个解决方案是一个纯 JS 解决方案,不依赖于 jQuery。这里的解决方案类似于使用&lt;form onsubmit="alert('hi'); return false;"&gt;
  • @ChrisMarisic - 几年前 :) 我已经更新了答案以包含 jQuery
  • 非常感谢 :)
【解决方案3】:

&lt;form onSubmit="return captureForm()"&gt; 应该这样做。确保您的 captureForm() 方法返回 false

【讨论】:

  • 跟进:有没有办法在不影响浏览器对所需属性的处理的情况下,用 JavaScript 捕获表单提交?
  • @Elisabeth 处理什么属性?如果您的意思是不阻止表单实际提交,您只需要captureForm() 返回true 而不是false
  • 浏览器对“必需”属性的处理。我确实想阻止提交表单。但是通过返回 false 而不是 true(或使用 preventDefault()),它会改变浏览器处理输入元素上“必需”属性的方式。亲自尝试一下:将 required 添加到输入元素,捕获提交并查看是否丢失了它的默认行为。
  • 我似乎没有失去默认行为。它在 Chrome 中运行良好。你需要想出一个错误的例子才能让我帮忙。
  • 好的,这是表格:
    下面是代码:function processForm(e) { var form = document .querySelector("表格"); for (var i = 0; i / } / 做事 return false; */ } 在歌剧中测试。取消注释最后一行,必需的失败。 (抱歉代码在 cmets 中不好用)
【解决方案4】:

处理我在实践中使用的所有请求的另一个选项是处理 javascript 提交、html 提交、ajax 请求。 这些代码应该添加到 body 元素的顶部,以便在任何表单呈现和提交之前创建监听器。

在示例中,我在提交页面时将隐藏字段设置为页面上的任何表单,即使它发生在页面加载之前。

//Handles jquery, dojo, etc. ajax requests
(function (send) {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    XMLHttpRequest.prototype.send = function (data) {
        if (isNotEmptyString(token) && isNotEmptyString(header)) {
            this.setRequestHeader(header, token);
        }
        send.call(this, data);
    };
})(XMLHttpRequest.prototype.send);


//Handles javascript submit
(function (submit) {
    HTMLFormElement.prototype.submit = function (data) {
        var token = $("meta[name='_csrf']").attr("content");
        var paramName = $("meta[name='_csrf_parameterName']").attr("content");
        $('<input>').attr({
            type: 'hidden',
            name: paramName,
            value: token
        }).appendTo(this);

        submit.call(this, data);
    };
})(HTMLFormElement.prototype.submit);


//Handles html submit
document.body.addEventListener('submit', function (event) {
    var token = $("meta[name='_csrf']").attr("content");
    var paramName = $("meta[name='_csrf_parameterName']").attr("content");
    $('<input>').attr({
        type: 'hidden',
        name: paramName,
        value: token
    }).appendTo(event.target);
}, false);

【讨论】:

    【解决方案5】:

    使用@Kristian Antonsen 的答案,或者您可以使用:

    $('button').click(function() {
        preventDefault();
        captureForm();
    });
    

    【讨论】:

    • 对于 2.5 年(或更长时间)后执行此操作的其他人,您需要将点击事件作为参数传递给函数(如 function(e) 并调用 e.preventDefault()
    • 也可以在表单的“提交”事件中被捕获,如果你的 input[type="submit"] 被使用,这会让你进入表单上下文而不是按钮上下文。回调将始终具有事件的上下文,因此您不必将“e”作为参数传递,您只需引用“事件”即可。
    • 不建议这样做,因为可以通过按键触发提交。
    【解决方案6】:

    使用 addEventListener 和 event.preventDefault 的另一种方法是更改​​表单提交本身。这种方法看起来更健壮,尤其是在表单附加了其他事件侦听器的情况下。

    我们可以使用以下代码更新表单提交:

    form.originSubmit = form.submit
    form.submit = function () {
      submitHandlerAsync(form)
      return false
    }
    

    在帖子中查看更多详细信息:https://runkiss.blogspot.com/2021/05/intercept-html-forms-submit.html

    【讨论】:

      猜你喜欢
      • 2012-04-09
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多