JavaScript post 请求就像表单提交一样

IT技术 javascript forms post submit
2020-12-14 15:57:36

我正在尝试将浏览器定向到不同的页面。如果我想要一个 GET 请求,我可能会说

document.location.href = 'http://example.com/q=a';

但是除非我使用 POST 请求,否则我尝试访问的资源将无法正确响应。如果这不是动态生成的,我可能会使用 HTML

<form action="http://example.com/" method="POST">
  <input type="hidden" name="q" value="a">
</form>

然后我会从 DOM 提交表单。

但我真的想要 JavaScript 代码,允许我说

post_to_url('http://example.com/', {'q':'a'});

什么是最好的跨浏览器实现?

编辑

对不起,我不清楚。我需要一个改变浏览器位置的解决方案,就像提交表单一样。如果这可以通过XMLHttpRequest 实现,那就不明显了。而且这不应该是异步的,也不应该使用 XML,所以 Ajax 不是答案。

6个回答

<input>在表单中动态创建s并提交

/**
 * sends a request to the specified url from a form. this will change the window location.
 * @param {string} path the path to send the post request to
 * @param {object} params the parameters to add to the url
 * @param {string} [method=post] the method to use on the form
 */

function post(path, params, method='post') {

  // The rest of this code assumes you are not using a library.
  // It can be made less verbose if you use one.
  const form = document.createElement('form');
  form.method = method;
  form.action = path;

  for (const key in params) {
    if (params.hasOwnProperty(key)) {
      const hiddenField = document.createElement('input');
      hiddenField.type = 'hidden';
      hiddenField.name = key;
      hiddenField.value = params[key];

      form.appendChild(hiddenField);
    }
  }

  document.body.appendChild(form);
  form.submit();
}

例子:

post('/contact/', {name: 'Johnny Bravo'});

编辑:由于这已经得到了如此多的支持,我猜人们会大量复制粘贴它。所以我添加了hasOwnProperty检查以修复任何无意中的错误。

@mricci 此代码段的重点是将浏览器重定向到操作指定的新 URL;如果您停留在同一页面上,您可以只使用传统的 AJAX 来发布您的数据。由于浏览器应该导航到新页面,因此当前页面的 DOM 内容无关紧要
2021-02-09 15:57:36
Python、Django 和 Flask 用户可能会看到此错误:“禁止 (403)。CSRF 验证失败。请求中止。”,如果从零创建表单。在这种情况下,您必须通过以下方式传递 csrf 令牌: post('/contact/', {name: 'Johnny Bravo', csrfmiddlewaretoken: $("#csrf_token").val()});
2021-02-11 15:57:36
令人惊奇的是,这既不是 html 也不是 javascript 不是 jquery 的本机支持..您必须对此进行编码。
2021-02-15 15:57:36
数据参数中的数组呢?Jquery post() 将例如:“data: {array: [1, 2, 3]}”解释为 ?array=1&array=2&array=3。Whi 代码给出了另一个结果。
2021-02-24 15:57:36
警告:尽管有很多赞成票,但此解决方案是有限的,并且无法处理表单内的数组或嵌套对象。否则,这是一个很好的答案。
2021-02-25 15:57:36

这将是使用jQuery所选答案的一个版本

// Post to the provided URL with the specified parameters.
function post(path, parameters) {
    var form = $('<form></form>');

    form.attr("method", "post");
    form.attr("action", path);

    $.each(parameters, function(key, value) {
        var field = $('<input></input>');

        field.attr("type", "hidden");
        field.attr("name", key);
        field.attr("value", value);

        form.append(field);
    });

    // The form needs to be a part of the document in
    // order for us to be able to submit it.
    $(document.body).append(form);
    form.submit();
}
如果 value 包含 dangeours xml 字符,则这在 ASP.NET 中不起作用。 encodeUriComponent(value) 是必需的。然后,服务器端也需要 UrlDecode。
2021-02-07 15:57:36
如果你的需求很简单,那么这个功能就没有必要了。这个单行就足够了:$("<form method='POST' action='https://example.com'><input type='hidden' name='q' value='a'/></form>").appendTo("body").submit();
2021-02-10 15:57:36
稍微修改它以支持数组和对象gist.github.com/hom3chuk/692bf12fe7dac2486212
2021-03-08 15:57:36

@Aaron 答案的简单快速实现:

document.body.innerHTML += '<form id="dynForm" action="http://example.com/" method="post"><input type="hidden" name="q" value="a"></form>';
document.getElementById("dynForm").submit();

当然,您应该使用 JavaScript 框架,例如PrototypejQuery ...

如何在此处插入 csrf?
2021-02-20 15:57:36
@Shulz 您可以添加另一个隐藏输入,[name]设置为键,并[value]设置为令牌值。
2021-03-07 15:57:36
有没有办法在当前浏览器窗口/选项卡中没有加载网页的情况下执行此操作?
2021-03-09 15:57:36

使用此答案中createElement提供函数,这是必要的,因为IE 破坏了通常使用以下方法创建的元素上的 name 属性document.createElement

function postToURL(url, values) {
    values = values || {};

    var form = createElement("form", {action: url,
                                      method: "POST",
                                      style: "display: none"});
    for (var property in values) {
        if (values.hasOwnProperty(property)) {
            var value = values[property];
            if (value instanceof Array) {
                for (var i = 0, l = value.length; i < l; i++) {
                    form.appendChild(createElement("input", {type: "hidden",
                                                             name: property,
                                                             value: value[i]}));
                }
            }
            else {
                form.appendChild(createElement("input", {type: "hidden",
                                                         name: property,
                                                         value: value}));
            }
        }
    }
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
}
提交后是否需要移除子项?页面不会消失吗?
2021-02-24 15:57:36
@CantucciHQ 即使未设置表单目标,页面也可能保持不变。例如,204 No Content
2021-03-01 15:57:36
提交后删除子项没有用,除非使用会话并保存这些数据。
2021-03-05 15:57:36

拉克什排的回答是惊人的,但对我来说发生(在一个问题Safari浏览器),当我尝试发布了一个名为域的表单submit例如,post_to_url("http://google.com/",{ submit: "submit" } );我已经稍微修补了这个函数来绕过这个可变空间碰撞。

    function post_to_url(path, params, method) {
        method = method || "post";

        var form = document.createElement("form");

        //Move the submit function to another variable
        //so that it doesn't get overwritten.
        form._submit_function_ = form.submit;

        form.setAttribute("method", method);
        form.setAttribute("action", path);

        for(var key in params) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
        }

        document.body.appendChild(form);
        form._submit_function_(); //Call the renamed function.
    }
    post_to_url("http://google.com/", { submit: "submit" } ); //Works!
Safari 是否仍然存在需要此解决方法的问题?
2021-02-12 15:57:36
2018 仍然不是更好的答案?
2021-03-05 15:57:36
该解决方案在 safari 浏览器和 iphone 11 chrome 浏览器/safari 浏览器中不起作用..在导航时我们“网络连接丢失”。任何人都可以就此提出建议。@弗利姆,
2021-03-08 15:57:36