Javascript IE中的事件处理
下面包含的代码允许我在用户第一次将鼠标移到某个元素上时执行某些操作,然后删除该事件 它在W3C事件模型浏览器中运行良好,但在IE6-8中不断抛出错误。我从另一个问题得到了代码,并相信它能处理IE。有人看到我做错了什么吗Javascript IE中的事件处理,javascript,javascript-events,event-handling,Javascript,Javascript Events,Event Handling,下面包含的代码允许我在用户第一次将鼠标移到某个元素上时执行某些操作,然后删除该事件 它在W3C事件模型浏览器中运行良好,但在IE6-8中不断抛出错误。我从另一个问题得到了代码,并相信它能处理IE。有人看到我做错了什么吗 <script type="text/javascript"> function setMouseEvent() { //Tel: 01 8279 400 event = addEvent(document.getEle
<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>
函数setMouseeEvent(){
//电话:018279400
event=addEvent(document.getElementById('contactButton'),'mouseover',changeText);
}
函数changeText(){
警惕(“工作!”);
removeEvent(document.getElementById('contactButton')、'mouseover',changeText);
}
功能加法器(obj,类型,fn){
if(obj.addEventListener的类型!=未定义){
obj.addEventListener(类型,fn,false);
}
else if(obj.attachEvent的类型!=未定义){
对象附件(“on”+类型,fn);
}
}
功能移除事件(obj,类型,fn){
if(obj.addEventListener的类型!=未定义){
对象removeEventListener(类型,fn,false);
}
else if(obj.attachEvent的类型!=未定义){
obj.detachEvent(“on”+类型,obj[type+fn]);
obj[type+fn]=null;
obj[“e”+类型+fn]=空;
}
}
window.onload=setMouseEvent;
更新:我刚刚测试了最新的Chrome、Opera和FF,没有任何问题,但是当我将鼠标移到Safari上时,Safari什么也不做,IE正在将错误重新加载,如前所述。如果您想要灵活的解决方案,请选择:
// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini
// http://dean.edwards.name/weblog/2005/10/add-event/
function addEvent(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else {
// assign each event handler a unique ID
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
// create a hash table of event types for the element
if (!element.events) element.events = {};
// create a hash table of event handlers for each element/event pair
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
// store the existing event handler (if there is one)
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
// store the event handler in the hash table
handlers[handler.$$guid] = handler;
// assign a global event handler to do all the work
element["on" + type] = handleEvent;
}
};
// a counter used to create unique IDs
addEvent.guid = 1;
function removeEvent(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else {
// delete the event handler from the hash table
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
}
};
function handleEvent(event) {
var returnValue = true;
// grab the event object (IE uses a global event object)
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
// get a reference to the hash table of event handlers
var handlers = this.events[event.type];
// execute each event handler
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
return returnValue;
};
function fixEvent(event) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function() {
this.returnValue = false;
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
};
addEvent
不返回任何内容;您正在将未定义的
缺少返回值分配给全局变量事件
(因为您在函数中没有说var事件
)。这将导致IE中出现异常,该异常使用全局事件
作为特殊对象将事件详细信息传递给处理程序,因此不允许为其分配其他内容
if (typeof obj.addEventListener != undefined)
typeof
始终返回一个字符串,该字符串的测试值永远不会等于未定义的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未对格式进行标准化(“返回函数的依赖于实现的表示”);有,;同样重要的是,对于浏览器当前的序列化方法,两个不同的函数可以轻松返回相同的字符串:
var f1= function() {};
var f2= function() {};
f1
和f2
将具有相同的字符串序列化,但它们不是相同的对象。如果在IE上为f1
添加了一个addEvent
,然后为f2
添加了另一个,则第二个属性将使用相同的序列化字符串并覆盖第一个属性。然后为f1
调用removeEvent
将检索f2
的函数,尝试detachEvent
并失败,因为它不是同一个函数。这个例子看起来有些做作,但实际上,当您使用通用闭包时,很容易发生意外,因为现代JavaScript现在做的越来越多。因此,我建议在所有情况下都避免Resig的addEvent
(jQuery用户:别担心,jQuery不会因为使用此代码而陷入陷阱。)
当IE调用你的changeText
函数时,IE的attachEvent
没有设置This
时,这个hack可以保留This
值。但是您甚至不使用这个
值,因此您可以使用一个更简单的版本,比如它被创建来替换的版本
至少,当您使用this
在IE上进行测试时,该addEvent的缺点是众所周知的,并且会立即显示出来,而不仅仅是在某个特定情况下出错,当它影响到您时,可能会非常混乱,难以调试
同样,您当前甚至没有为同一事件使用多个侦听器,因此您可以轻松地使用老式的DOM Level 0事件处理程序,例如:
window.onload= function() {
var changed= false;
document.getElementById('contactButton').onmouseover= function() {
if (!changed) {
alert('changing text');
}
changed= true;
};
};
讨厌。你从哪里得到的removeEvent
?看起来类似于John Resig的实现(),但与addEvent
并不对称。也许我只是个傻瓜,但如果这是我的页面,我会用一个简单的标志变量处理一次性事件处理程序,我会在第一次调用后翻转它。如果我真的想做大量的事件争论,我会让一些经过良好测试的框架来处理难看的细节。一直想继续学习。我想这是第一个答案,可以解决Resig的addEvent
条目的不足。在对这个答案的评论中有一个简短的交流:kangax告诉我依赖函数反编译的失败之处
window.onload= function() {
var changed= false;
document.getElementById('contactButton').onmouseover= function() {
if (!changed) {
alert('changing text');
}
changed= true;
};
};