下面包含的代码允许我在用户第一次将鼠标悬停在元素上时执行某些操作,然后删除该事件。
它在 W3C 事件模型浏览器中运行良好,但在 IE6-8 中不断抛出错误。我从另一个问题中得到了代码,并相信它可以处理 IE。有人看到我做错了什么吗?
<script type="text/javascript">
function setMouseEvent() {
//Tel: 01 8279 400
event = addEvent(document.getElementById('contactButton'), 'mouseover', changeText);
}
function changeText() {
alert("worked!");
removeEvent(document.getElementById('contactButton'), 'mouseover', changeText);
}
function addEvent(obj, type, fn) {
if (typeof obj.addEventListener != undefined) {
obj.addEventListener(type, fn, false);
}
else if (typeof obj.attachEvent != undefined) {
obj.attachEvent("on" + type, fn);
}
}
function removeEvent(obj, type, fn) {
if (typeof obj.addEventListener != undefined) {
obj.removeEventListener(type, fn, false);
}
else if (typeof obj.attachEvent != undefined) {
obj.detachEvent("on" + type, obj[type + fn]);
obj[type + fn] = null;
obj["e" + type + fn] = null;
}
}
window.onload = setMouseEvent;
</script>
更新:我刚刚在最新的 Chrome、Opera 和 Firefox 中进行了测试,没有出现任何问题,但当我将鼠标悬停在 Safari 上时,Safari 不会执行任何操作,并且 IE 会抛出错误 onload
,如上所述.
最佳答案
event = addEvent(
addEvent
不返回任何内容;您将 undefined
缺乏返回值分配给全局变量 event
(因为您没有在功能)。这将导致 IE 中出现异常,它使用全局 event
作为特殊对象将事件详细信息传递给处理程序,因此不允许您为其分配其他内容。
if (typeof obj.addEventListener != undefined)
typeof
始终返回一个字符串,该字符串永远不会测试等于 undefined
unvalue,因此 IE 将始终采用非 IE fork 并失败。您的意思是 if (typeof obj.addEventListener !== 'undefined')
,带有一个字符串。
obj.detachEvent("on" + type, obj[type + fn]);
由于您没有在 addEvent
函数中编写名称为 type
和 fn
的属性,因此这将失败检索任何内容。
正如 Crescent 所说,您似乎正在使用 Resig 的 removeEvent
函数,并与另一个不匹配的 addEvent
配对。如果您使用他的 removeEvent
,您将需要使用他的 addEvent
来配合它。
但是,无论如何我都不会使用这些函数:它们非常危险。我知道那是 2005 年,当时这个构思不周的代码“赢得”了 quirksmode 的 addEvent 竞赛,但即便如此,我们也应该了解得更多。问题是它根据事件名称和函数代码的文本序列化 (type+fn
) 创建一个字符串,并将其用作存储回调的键。该键看起来类似于 'mouseoverfunction changeText() {...code...}'
。
但是依赖函数序列化是一个糟糕的主意。 ECMAScript 未对格式进行标准化(“返回函数的依赖于实现的表示。”);有many browser quirks ;尤其重要的是,两个不同的函数可以轻松地为浏览器当前的序列化方法返回相同的字符串:
var f1= function() {};
var f2= function() {};
f1
和 f2
将具有相同的字符串序列化,但它们不是同一个对象。如果您在 IE 上为 f1
执行了 addEvent
,然后为 f2
执行了另一个 addEvent
,则第二个属性将使用相同的序列化字符串并覆盖第一个属性(property)。然后调用 f1
的 removeEvent
将检索 f2
的函数,尝试 detachEvent
它并失败,因为它不是相同的功能。这个例子可能看起来很做作,但实际上当你使用通用闭包时,它很容易意外发生,就像现代 JavaScript 现在越来越多地这样做一样。因此,我建议在所有情况下避免使用 Resig 的 addEvent
。
(jQuery 用户:不用担心,尽管存在所有问题,jQuery 不会陷入使用此代码的陷阱。)
当 IE 回调您的 changeText
函数时,此 hack 的作用是保留 this
值,而 IE 的 attachEvent
未设置 这个
。但您甚至不使用 this
值,因此您可以使用更简单的版本,例如 original addEvent它的创建是为了取代。
至少 addEvent 的缺点是众所周知的,并且当您使用 this
在 IE 上进行测试时会立即显现出来,而不是仅在特定情况下出错,当它影响到你时,很可能会非常令人困惑并且难以调试。
话又说回来,您当前甚至没有为同一个事件使用多个监听器,因此您可以轻松地使用老式 DOM Level 0 事件处理程序,例如:
window.onload= function() {
var changed= false;
document.getElementById('contactButton').onmouseover= function() {
if (!changed) {
alert('changing text');
}
changed= true;
};
};
关于javascript - IE 中的事件处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3185513/