我有以下代码:
<head>
<script>
function startChanging() {
var elems = document.getElementsByTagName("img");
for(var i=0; i < elems.length; i++)
{
var xmlhttp;
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp["elem"] = elems[i];
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
this["elem"].src = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "http://myurl.com/somescript.php", true);
xmlhttp.send();
}
};
</script>
</head>
<body onload="startChanging()">
<img src="https://www.google.com/images/srpr/logo11w.png">
<br/>
<img src="https://www.google.com/images/srpr/logo11w.png">
<br/>
<img src="https://www.google.com/images/srpr/logo11w.png">
</body>
即使我为每次迭代创建了一个XMLHttpRequest
的新实例并将当前元素添加到属性,但当请求返回响应时,只会更改最后一个img
元素。
我正在寻找一个简单的解决方案来更改src
元素的img
,而不会在响应到来时再次遍历所有元素。我想要一个纯粹的Javascript解决方案(阅读:没有JQuery)。
我肯定在这里做错了我只是不明白什么。任何帮助将不胜感激。
答案 0 :(得分:2)
在for
循环中,您正在覆盖xmlhttp
变量,因此当您进入onreadystatechage
函数并检查xmlhttp.readyState
的值时,它将不会检查正确的对象。
我建议这个修改可以改变两件事:
xmlhttp
变量与每个ajax调用分开。elems[i]
传递到闭包中,因此您无需执行属性保存黑客攻击。代码:
function startChanging() {
var elems = document.getElementsByTagName("img");
for(var i=0; i < elems.length; i++)
{
(function(obj) {
var xmlhttp;
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
obj.src = xmlhttp.responseText;
}
}
xmlhttp.open("GET", "http://myurl.com/somescript.php", true);
xmlhttp.send();
})(elems[i]);
}
};
答案 1 :(得分:1)
一种可能的方法:
xmlhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
this.elem.src = this.responseText;
}
}
如您所见,我已将该处理程序函数中对xmlhttp
的所有引用替换为this
。
问题是即使你已经在循环的每一步创建了一个新的AJAX服务对象,每个新创建的'readystatechange'
处理函数都引用xmlhttp
下已知的同一个对象变量
通常,当有人使用在同一循环中创建的函数引用的循环内声明的变量时,这是一个非常常见的问题。偶然发现一两次,你会开始看到这种模式。 )
答案 2 :(得分:0)
xmlhttp.send();
将数据放入send方法:
xmlhttp.send(data);
来源:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
void send();
void send(ArrayBuffer data);
void send(ArrayBufferView data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);
data
是一个JavaScript变量,你可以放任何东西。如果你想要多部分消息,你可以使用var data = new FormData();
并使用data.append('image', file);
将数据放入其中,例如通过ajax上传文件。
如果没有多部分,只需输入任何内容:
data = { images: document.getElementsByTagName("img") }