我正在尝试将浏览器指向另一个页面。如果我想要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'});
最好的跨浏览器实现是什么?
我需要一个改变浏览器位置的解决方案,就像提交表单一样。这不应该是异步的,也不应该使用XML,因此Ajax不是答案。
不可以。您不能像提交表单一样提交JavaScript发布请求。
您可以拥有HTML格式的表单,然后使用JavaScript提交它。(如本页多次所述)。
您可以自己创建HTML,不需要JavaScript来编写HTML。如果有人这样建议,那就太傻了。
<form id="ninja" action="http://example.com/" method="POST">
<input id="donaldduck" type="hidden" name="q" value="a">
</form>
您的函数将按照您想要的方式配置表单。
function postToURL(a,b,c){
document.getElementById("ninja").action = a;
document.getElementById("donaldduck").name = b;
document.getElementById("donaldduck").value = c;
document.getElementById("ninja").submit();
}
然后,像这样使用它。
postToURL("http://example.com/","q","a");
但我会省略函数,只做。
document.getElementById('donaldduck').value = "a";
document.getElementById("ninja").submit();
最后,样式决定在ccs文件中。
#ninja {
display: none;
}
就我个人而言,我认为表格应该用名字来称呼,但现在这并不重要。
Rakesh Pai的回答令人惊讶,但当我试图发布一个名为submit的表单时,我(在Safari中)遇到了一个问题。例如,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!
这将是使用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();
}
还有另一个递归解决方案,因为其他一些似乎已被破坏(我没有测试所有这些)。这取决于lodash 3.x和ES6(不需要jQuery):
function createHiddenInput(name, value) {
let input = document.createElement('input');
input.setAttribute('type','hidden');
input.setAttribute('name',name);
input.setAttribute('value',value);
return input;
}
function appendInput(form, name, value) {
if(_.isArray(value)) {
_.each(value, (v,i) => {
appendInput(form, `${name}[${i}]`, v);
});
} else if(_.isObject(value)) {
_.forOwn(value, (v,p) => {
appendInput(form, `${name}[${p}]`, v);
});
} else {
form.appendChild(createHiddenInput(name, value));
}
}
function postToUrl(url, data) {
let form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', url);
_.forOwn(data, (value, name) => {
appendInput(form, name, value);
});
form.submit();
}
好吧,希望我读过所有其他帖子,这样我就不会浪费时间从Rakesh Pai的回答中创建这些帖子了。这里有一个递归解决方案,可以处理数组和对象。不依赖jQuery。
添加了一个段来处理整个表单应该像数组一样提交的情况。(即,项目列表周围没有包装对象)
/**
* Posts javascript data to a url using form.submit().
* Note: Handles json and arrays.
* @param {string} path - url where the data should be sent.
* @param {string} data - data as javascript object (JSON).
* @param {object} options -- optional attributes
* {
* {string} method: get/post/put/etc,
* {string} arrayName: name to post arraylike data. Only necessary when root data object is an array.
* }
* @example postToUrl('/UpdateUser', {Order {Id: 1, FirstName: 'Sally'}});
*/
function postToUrl(path, data, options) {
if (options === undefined) {
options = {};
}
var method = options.method || "post"; // Set method to post by default if not specified.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
function constructElements(item, parentString) {
for (var key in item) {
if (item.hasOwnProperty(key) && item[key] != null) {
if (Object.prototype.toString.call(item[key]) === '[object Array]') {
for (var i = 0; i < item[key].length; i++) {
constructElements(item[key][i], parentString + key + "[" + i + "].");
}
} else if (Object.prototype.toString.call(item[key]) === '[object Object]') {
constructElements(item[key], parentString + key + ".");
} else {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", parentString + key);
hiddenField.setAttribute("value", item[key]);
form.appendChild(hiddenField);
}
}
}
}
//if the parent 'data' object is an array we need to treat it a little differently
if (Object.prototype.toString.call(data) === '[object Array]') {
if (options.arrayName === undefined) console.warn("Posting array-type to url will doubtfully work without an arrayName defined in options.");
//loop through each array item at the parent level
for (var i = 0; i < data.length; i++) {
constructElements(data[i], (options.arrayName || "") + "[" + i + "].");
}
} else {
//otherwise treat it normally
constructElements(data, "");
}
document.body.appendChild(form);
form.submit();
};