javascript - 如何使用 JavaScript 动态更改事件处理程序?

标签 javascript php dom-events

我对 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) addEventListenerremoveEventListener 使用较新的 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-oversrcdata-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 库来消除浏览器差异并为您实现有用的功能。例如,使用 addEventListenerremoveEventListener 的代码在 IE9 之前的 IE 上将失败,因为它根本没有这些方法。如果您使用像 jQuery 这样的库, Prototype , YUI , Closure ,或any of several others ,他们会为您处理这些事情,以便您可以专注于自己的增值。

题外话#2:当鼠标经过元素时,mouseover 事件会重复发生,并且它和 mouseout 都会冒泡上 DOM。这意味着,对于像您这样的悬停效果,如果您不能使用 CSS(并且在 IE6 上也不能),那么您最好使用 mouseentermouseleave事件,大多数时候。但这些是 IE 特定的事件,大多数其他浏览器不支持。输入任何合适的 JavaScript 库。 :-) 他们将在不直接支持它们的浏览器上模拟 mouseentermouseleave。在上面的列表中,我确信 jQuery 和 Prototype 可以做到这一点;如果其他人没有类似的功能,我会感到惊讶。

关于javascript - 如何使用 JavaScript 动态更改事件处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4577995/

相关文章:

JavaScript 表单验证为 false 时

javascript - 如何向数组中的对象添加一个值,该值是另一个对象中键的值?

javascript - 在子选项卡之间导航时,父 Controller 是否会再次重新初始化?

javascript - 如何获取父 div 元素的子元素

php - 如何在foreach循环下将数组合并为一个数组

php - Laravel Forge 将非 www 重定向到 www

php - 我正在尝试将复选框连接到 PHP 中的 SQL 语句中

javascript - 头部异步 JS 加载

javascript - Angular 5 : creating a parent component with an external template and overriding the inner part

javascript - 带鼠标滚轮的 addEventListener 在 Firefox 中不起作用