架构爱好者
学习交流中心

事件代理/委托

事件代理/委托,是靠事件的冒泡机制实现的(所以,对于一些不具有冒泡特性的事件,比如focus、blur,就没有事件代理/委托这种说法了)。

一、优缺点

优点有:

  • 可以大量节省内存占用,减少事件注册,比如在table上代理所有td的click事件就非常棒;
  • 可以实现当新增子孙节点时无需再次对其绑定事件,对于动态内容部分尤为合适。

缺点有:

  • 如果把所有事件都代理到一个比较顶层的DOM节点上的话,比较容易出现误判,给不需要绑定事件的节点绑定了事件,比如把页面中所有事件都绑定到document上进行委托,就不是很合适;
  • 事件逐级冒泡到外部dom上再执行肯定没有直接执行快。

二、实现

// 只考虑IE 9&+
function delegate(element, targetSelector, type, handler) {
    element.addEventListener(type, function(e) {
        var targets = Array.prototype.slice.call(element.querySelectorAll(targetSelector))
        var target = e.target
        if (targets.indexOf(target) !== -1) {
            return handler.apply(target, arguments)
        }
    })
}

// 兼容写法
function delegate(element, targetClass, type, handler) {
    addEvent(element, type, function(e) {
        e = e || window.event
        var target = e.target || e.srcElement
        if (target.className.indexOf(targetClass) !== -1) {
            handler.apply(target, arguments)
        }
    })
}

function addEvent(target, type, listener) {
    if (target.addEventListener) {
        // non-IE, IE9&+
        target.addEventListener(type, listener, false)
    } else if (target.attachEvent) {
        // IE6 - IE10, not available in IE11
        target.attachEvent('on' + type, listener)
    } else {
        // all browsers
        target['on' + type] = listener
    }
}

说明:上面的实现方案中addEvent方法的最后一种实现方式, 即target['on' + type]的方式会将之前绑定的事件覆盖掉,是有点问题的。 但是考虑到兼容性,一般来说代码是走不到这个地方的,所以也没有问题。

未经允许不得转载:技术杂烩 » 事件代理/委托