我注意到事件可以直接在对象上分配,而不必使用addEventListener:
document.onload = function(e){
// do stuff..
};
而不是:
document.addEventListener('load', function(e){
// do stuff..
});
那么我有什么理由不使用第一种方法吗?为什么其他人不使用它?
此外,这似乎也适用于旧的IE(你需要attachEvent)。
答案 0 :(得分:3)
考虑如果您尝试以下操作会发生什么(我将事件附加到window
,因为这是您应该监听此事件的地方)
window.onload = function (e) {console.log('A');};
window.onload = function (e) {console.log('B');};
VS
window.addEventListener('load', function (e) {console.log('C');}, false);
window.addEventListener('load', function (e) {console.log('D');}, false);
从第一个代码块中,您只能看到"B"
,但从第二个代码块中,您会看到"C"
和"D"
。 Fiddle(请打开控制台查看)。
答案 1 :(得分:3)
除了接受的答案显示直接绑定到DOM的处理程序限制了处理程序的数量之外,addEventListener
还有更多要提供的内容:
事件监听器不需要直接绑定到元素(它不必存在于DOM中)。这在使用ajax时很有用(将其视为jQuery的.on
方法)
单个侦听器可以处理特定类型的所有事件,因此使用事件侦听器需要的资源更少(可以加快整体性能)
对于X-browser兼容性(如IE8),避免内存泄漏要容易得多:
window.onload = function(e)
{
alert('In IE8, this causes mem-leaks!');
};
var load = function(e)
{//cf @PaulS.'s comment & link on IE8 and symbol bleeding
e = e || window.event;//X-browser stuff
var target = e.target || e.srcElement;//so you can use this callback for all browsers
if (window.removeEventListener)
{//more X-browser stuff
return window.removeEventListener('load',load,false);
}
window.detachEvent('onload',load);//reference callback by variable name
};
if (window.addEventListener)
{
window.addEventListener('load',load,false);
}
else
{//in IE8, addEventListener doesn't exist, but it has a jScript counterpart:
//no mem-leaks in IE AFAIK
window.attachEvent('onload', load);
}
以下是您可能感兴趣的几个链接(是的,我知道,无耻的自我推销 - 抱歉):
Why do we need event listeners?
mem-leaks & event delegation & closures in IE8
只是为了好玩:一段时间我写的脚本使用事件委托,适用于IE,FF,chrome,... 和触摸设备。这比我想象的要复杂一点。
/**
* Copyright 2012, Elias Van Ootegem
* Date: Tue Jul 03 2012 +0100
*/
(function(G,undef)
{
'use strict';
var load,clickHandler,touchHandler,hide,reveal;
hide = function(elem)
{
elem.setAttribute('style','display:none;');
};
reveal = function(show,nextTo)
{
var str = 'display: block; position:relative; left:220px; top: ' + (nextTo.offsetTop - show.parentNode.offsetTop) + 'px;';
show.setAttribute('style',str);
}
load = function()
{
var doc = G.document;
if (G.removeEventListener)
{
G.removeEventListener('load',load,false);
}
else
{
G.detachEvent('onload',load);
}
if (doc.hasOwnProperty('ontouchstart'))
{//We have a touch device
touchHandler = (function(subNavs)
{
var current,divs = (function()
{
var i,r = {};
for (i=0;i<subNavs.length;i++)
{
r[subNavs[i].id] = doc.getElementById(subNavs[i].id + 'd');
hide(r[subNavs[i].id]);
}
return r;
}());
return function(e)
{
e = e || G.event;
if (e.changedTouches.length !== 1)
{//multi-touch
return e;
}
var timer,endListener,coords,target = e.target || e.srcElement;
if (target.tagName.toLowerCase() === 'img' && target.id.match(/^close[0-9]+$/))
{
hide(current);
current = undef;
return e;
}
if (target.tagName.toLowerCase() === 'a')
{
target = target.parentNode;
}
if (target.tagName.toLowerCase() !== 'p' || !target.id || !divs[target.id])
{
if (current === undef)
{
return e;
}
while(target !== doc.body)
{
target = target.parentNode;
if (target === current)
{
return e;
}
}
timer = setTimeout(function()
{
doc.body.removeEventListener('touchend',endListener,false);
clearTimeout(timer);
timer = undef;
},300);
endListener = function(e)
{
doc.body.removeEventListener('touchend',endListener,false);
clearTimeout(timer);
timer = undef;
hide(current);
current = undef;
return e;
};
return doc.body.addEventListener('touchend',endListener,false);
}
coords = {x:e.changedTouches[0].clientX,y:e.changedTouches[0].clientY};
timer = setTimeout(function()
{
doc.body.removeEventListener('touchend',endListener,false);
clearTimeout(timer);
timer = undef;
},300);
endListener = function(e)
{
e = e || G.event;
clearTimeout(timer);
timer = undef;
doc.body.removeEventListener('touchend',endListener,false);
var endCoords,endTarget = e.target || e.srcElement;
if (endTarget !== target)
{
endCoords = {x:e.changedTouches[0].clientX,y:e.changedTouches[0].clientY};
if (Math.abs(coords.x - endCoords.x) < 26 && Math.abs(coords.y - endCoords.y) < 26)
{
endTarget = target;
}
}
if (endTarget !== target)
{
return e;
}
if (current !== undef)
{
hide(current);
current = undef;
}
current = divs[target.id];
reveal(current,target);
};
doc.body.addEventListener('touchend',endListener,false);
};
}(doc.getElementsByClassName('subnavbar')));
return doc.body.addEventListener('touchstart',touchHandler,false);
}
clickHandler = (function(subNavs)
{
var current,divs = (function()
{
var i,r = {};
for (i=0;i<subNavs.length;i++)
{
r[subNavs[i].id] = doc.getElementById(subNavs[i].id + 'd');
hide(r[subNavs[i].id]);
}
return r;
}());
return function(e)
{
e = e || G.event;
var target = e.target || e.srcElement;
if (target.tagName.toLowerCase() === 'img' && target.id.match(/^close[0-9]+$/))
{
hide(current);
current = undef;
return e;
}
if (target.tagName.toLowerCase() === 'a')
{
target = target.parentNode;
}
if (target.tagName.toLowerCase() !== 'p' || !target.className.match(/\bsubnavbar\b/))
{
if (current !== undef)
{
target = (function()
{
while (target !== doc.body)
{
target = target.parentNode;
if (target === current)
{
return current;
}
}
}());
if (target !== current)
{
hide(current);
current = undef;
}
}
return e;
}
if (e.preventDefault)
{
e.preventDefault();
e.stopPropagation();
}
else
{
e.returnValue = false;
e.cancelBubble = true;
}
if (current !== undef)
{
hide(current);
}
current = divs[target.id];
reveal(current,target);
};
}(doc.getElementsByClassName('subnavbar')));
if (doc.body.addEventListener)
{
return doc.body.addEventListener('click',clickHandler,false);
}
return doc.body.attachEvent('onclick',clickHandler);
};
if (G.addEventListener)
{
return G.addEventListener('load',load,false);
}
return G.attachEvent('onload',load);
}(this));