我对 AJAX 还很陌生,遇到了以下问题。我希望这里有人能够帮助我。我确信这是一个简单的修复,但我只是没有看到它:(
我想做的是动态更改元素的 onmouseover 和 onmouseout 事件,以下是相关的代码:
HTML 元素(注意有多个元素,因此它们的 id 是动态部分)
<?
if (ownsgame($id, $userid)) {?>
<a><img src="images/collection/got.gif" id="ownedimage<?=$id?>" title="<?=$itemtitle?> (<?=$platformdisplay?>) is in your collection" alt="You own this game" align="center" width="62" height="22" onclick="changeOwned('<?=$id?>')" onmouseover="changeImageSrc('ownedimage<?=$id?>', 'images/collection/del.gif')" onmouseout="changeImageSrc('ownedimage<?=$id?>', 'images/collection/got.gif')"/></a>
<? } else { ?>
<a><img src="images/collection/add.gif" id="ownedimage<?=$id?>" title="Add <?=$itemtitle?> (<?=$platformdisplay?>) to your collection" alt="You do not own this game" align="center" width="62" height="22" onclick="changeOwned('<?=$id?>')" onmouseover="changeImageSrc('ownedimage<?=$id?>', 'images/collection/add.gif')" onmouseout="changeImageSrc('ownedimage<?=$id?>', 'images/collection/add.gif')"/></a>
<?} ?>
JavaScript 函数:
function changeImageSrc(id, src) {
document.getElementById(id).src = src;
}
(相关)AJAX 代码:
var http = createRequestObject();
var jsid = "";
function changeOwned(id) {
http.open('get', 'changeowned.php?id=' + id + '&user=<?=$userid?>');
jsid = id;
http.onreadystatechange = processResponse;
http.send(null);
}
function processResponse() {
if((http.readyState == 4) && (http.status == 200)){
var response = http.responseText;
var elementid = 'ownedimage' + jsid;
var element = document.getElementById(elementid);
if (response == "1") {
image = "images/collection/got.gif";
alt = "you own this game";
mouseoverstr = 'images/collection/del.gif';
mouseoutstr = 'images/collection/got.gif';
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/add.gif')}, false);
element.removeEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/add.gif')}, false);
} else {
image = "images/collection/add.gif";
alt = "add this game to your collection";
mouseoverstr = 'images/collection/add.gif';
mouseoutstr = 'images/collection/add.gif';
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/got.gif')}, false);
element.removeEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/del.gif')}, false);
}
element.src = image;
element.alt = alt;
element.addEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, mouseoverstr)}, false);
element.addEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, mouseoutstr)}, false);
}
}
一开始似乎工作正常,但会产生一些奇怪的行为。引用的 PHP 工作正常并产生正确的响应。图像的 srcand alt 也会更改。事实上,它首先看起来也像新的鼠标悬停/移出功能。但是,当您单击网站上的多个图像(具有不同的 ID)时,它们会突然开始相互影响。当您将鼠标悬停在其中一个上时,另一个也会更改其图像。为什么会发生这种情况?我真的很无能,因为 jsid 部分很好,我不明白为什么鼠标悬停会突然改变两个图像。看起来好像不同 ID 的多个事件处理程序被分配给同一个图像元素。不知道为什么会这样。我希望你们中一些有更多 AJAX 知识的人可以在这里帮助我,我很沮丧:(
最佳答案
有几件事::-)
1) addEventListener
和 removeEventListener
使用较新的 DOM2 处理程序链,它与旧的“DOM0”样式(onXYZ
属性)。因此,您无法通过 removeEventListener
删除最初通过 onXYZ
属性分配的处理程序。为此,请将“”分配给属性的反射属性。
element.onmouseover = "";
2) 当您使用removeEventListener
时,您必须传入您最初使用的相同函数引用。所以这永远不会删除任何东西:
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/got.gif')}, false);
...因为它创建了一个全新的函数来传递给 removeEventListener
,并且由于该函数不在事件处理程序链上,因此该调用将被忽略。
我可能会通过使用单个事件处理程序来解决这个问题,然后更改它所使用的数据。您可以通过使用 data-xyz
属性(例如 data-oversrc
和 data-stdsrc
或类似的)。然后你的两个函数(一个用于鼠标悬停,一个用于鼠标移出)根据图像更改 URL:
function handleMouseOver() {
this.src = this.getAttribute('data-oversrc');
}
function handleMouseOut() {
this.src = this.getAttribute('data-stdsrc');
}
我会从元素中完全删除 onXYZ
处理程序,并将其替换为一次性 addEventListener
(IE 上的 attachEvent
)分配这两个。
data-xyz
属性与所有自定义属性一样,在 HTML4 及更早版本中无效。从 HTML5 开始,它们已经过验证,而且由于主流浏览器都不存在无效属性的问题,因此您可以立即开始使用它们。
离题 #1:现在,我通常建议使用 JavaScript 库来消除浏览器差异并为您实现有用的功能。例如,使用 addEventListener
和 removeEventListener
的代码在 IE9 之前的 IE 上将失败,因为它根本没有这些方法。如果您使用像 jQuery 这样的库, Prototype , YUI , Closure ,或any of several others ,他们会为您处理这些事情,以便您可以专注于自己的增值。
题外话#2:当鼠标经过元素时,mouseover
事件会重复发生,并且它和 mouseout
都会冒泡上 DOM。这意味着,对于像您这样的悬停效果,如果您不能使用 CSS(并且在 IE6 上也不能),那么您最好使用 mouseenter
和 mouseleave
事件,大多数时候。但这些是 IE 特定的事件,大多数其他浏览器不支持。输入任何合适的 JavaScript 库。 :-) 他们将在不直接支持它们的浏览器上模拟 mouseenter
和 mouseleave
。在上面的列表中,我确信 jQuery 和 Prototype 可以做到这一点;如果其他人没有类似的功能,我会感到惊讶。
关于javascript - 如何使用 JavaScript 动态更改事件处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4577995/