addEventListener()的备用快捷方式

时间:2012-12-28 11:52:37

标签: javascript optimization javascript-events

  

可能重复:
  What is the difference of using addEventListener?

我注意到事件可以直接在对象上分配,而不必使用addEventListener:

document.onload = function(e){
  // do stuff..
};

而不是:

document.addEventListener('load', function(e){
  // do stuff..
});

那么我有什么理由不使用第一种方法吗?为什么其他人不使用它?

此外,这似乎也适用于旧的IE(你需要attachEvent)。

2 个答案:

答案 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));