在jQuery中,代码是这样的,一切皆大欢喜:
$.post("bucket.php", { empty:"1" }, function(r) { ... });
Firefox 开发工具中的控制台显示“表单数据”包含
empty=1
,PHP 文件得到了它想要的内容。我真的不明白这种语法({ }
做什么,而 empty
不在引号中),但它有效。
现在我需要用纯 Javascript 做同样的事情。这是我的代码:
function bucketEmpty() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) { //no error
if (!isNaN(xhr.responseText)) { // return string is a number (expecting 0)
document.getElementsByClassName('bucketcount').innerHTML = xhr.responseText;
} else {
alert(xhr.responseText);
}
}
};
xhr.open('POST', 'bucket.php');
xhr.send(???what goes here???);
}
对于 xhr.send() 的参数,我尝试了以下方法,但都不起作用:
'empty=1'
(根据this answer):控制台说它在“请求有效负载”中,而不是“表单数据”中。{empty:"1"}
或 {"empty":"1"}
:控制台显示“请求负载”包含“[对象对象]”。'{"empty":"1"}'
:控制台说它在一个名为“JSON”的部分中。这对于 GET 来说很容易,但由于它正在更改服务器上的某些内容,因此 POST 更合适。什么是正确的语法?
编辑以回应 Rayon 和 Atul Sharma:
嗯,其他基本问题一定是错的。对于诊断,我目前将其作为 bucket.php 中的第一行:
die("GET:\n".print_r($_POST,true)."\nPOST:\n".print_r($_POST,true));
无论我使用
xhr.send(JSON.stringify({empty: '1'}))
(Atul Sharma 的回答)还是 xhr.send('{"empty":"1"}')
(Rayon 的评论),我都会得到控制台截图和服务器输出中显示的结果:
我决定测试 GET - 我将打开命令更改为:
xhr.open('GET', 'bucket.php?empty=1');
控制台说查询字符串包含
empty: "1"
,但是在服务器上$_GET
和$_POST
仍然是空的!香草 JS 只是讨厌我吗?这在 jQuery 中运行良好。
编辑#2:只有我(或我的服务器)!
在发现连我原来最简单的语法在jsfiddle(https://jsfiddle.net/3j42ztpf/)上都可以工作后,我为自己的服务器写了一个WME测试文件对。在我的本地 VM 和我的生产 VPS 上,它的行为方式相同 - jQuery 工作但普通 JS 不工作,无论参数是作为文本还是 JSON 发送。在 JSFiddle 测试和我的服务器测试的第一个链接之间的 HTTP 请求中肯定有一些不同,但我无法在 devtools 中发现它 - 请求有效负载是相同的,标头中的差异似乎都是合乎逻辑的。自己尝试:https://dev.kizunadb.com/testajax.html
后端文件testajax.php只有这个:
<?php
if (empty($_POST['text'])) {
die('What do you want me to say?');
} else {
die ($_POST['text']);
}
所以我确实有一个比糟糕的语法更根本的问题。任何人都可以在他们的开发工具中发现问题,或者建议我应该检查我的服务器吗?
在研究@StackSlave 和@Rayon 的评论中的建议时,我了解了更多有关 Content-Type 的知识。事实证明,我所需要的只是将 Content-Type 设置为“application/x-www-form-urlencoded”。所有三个试图提供帮助的人(其中一个人后来删除了他们的答案)都专注于以 JSON 格式来回传递数据,但在这种情况下这真的没有必要,只会让代码更难阅读(无论如何在我看来)。所以这是该函数的最终版本,重点是最后两行(我还必须更改将返回的数字写入 DOM 的方式 - getElementsByClassName 返回一个必须正确处理的 HTMLCollection):
function bucketEmpty() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) { //no error
if (!isNaN(xhr.responseText)) { // return string is a number (expecting 0)
var elements = document.getElementsByClassName('bucketcount');
[].forEach.call(elements, function (el) { el.innerHTML = xhr.responseText; });
} else {
alert(xhr.responseText);
}
}
};
xhr.open('POST', 'bucket.php');
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send('empty=1');
}
特别有用的 SO 答案和其他页面是:
getElementsByClassName()
- 不是我的实际问题,但有人可能想知道 forEach.call 代码来自哪里)xhr.send('empty=1');
这是否意味着 php 文件中的 $_POST['empty']?