Javascript事件事件委托(事件代理)

事件委托(事件代理)

有了事件冒泡和事件捕获的基础,事件委托应该是比较容易学习了。什么是事件委托?对“事件处理程序过多”问题的解决方案就是事件委托。
事件委托利用了事件冒泡,只定义一个事件处理程序,就可以管理某一类型的所有事件。例如,click事件会冒泡到document层次,也就是说,我们可以为整个页面指定一个onclick事件处理程序,而不必给每个可单击的元素分别添加事件处理程序。下面我们具体举个例子来解释如何使用这个特性:

举个经常举的例子,比如有如下代码:

1
2
3
4
5
6
7
8
<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>
</ul>

需要的效果是每点击相应的

  • 选项,alert它里面的内容,或许很简单:
    1
    2
    3
    4
    5
    6
    7
    8
    window.onload = function() {  
    var lis = document.getElementsByTagName('li');
    for(var i = 0, len = lis.length; i < len; i++) {
    lis[i].onclick = function() {
    console.log(this.innerHTML);
    };
    }
    }
  • 要给每个li添加一个点击事件,我们通常的写法,是为每个li添加一个onClick的处理函数,但是如上代码绑定了很多个事件,我们知道每个事件绑定都需要占用一定的内存,更糟糕的是,如果在代码执行过程中,动态地又添加了一个li,这时它没有绑定click的事件,我们还需要手动添加!
    这时,我们就可以用到事件委托技术:使用事件冒泡机制,当事件冒泡到更上层的父节点的时候,我们通过判断Event对象的目标对象(target)来判断并获取事件源li。下面的代码可以完成我们想要的效果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    window.onload = function() {  
    //获取父节点,并为它添加一个click事件
    document.getElementById("parent-list").addEventListener("click",function(e) {
    //检查事件源e.targe是否为li
    if(e.target && e.target.nodeName.toUpperCase() == "LI") {
    console.log("List item " + e.target.id + " was clicked!");
    }
    e.stopPropagation(); //阻止事件继续冒泡
    });
    }

    好吧,就是这这样!

    优缺点

    JavaScript事件代理使用的好处:
    1、那些需要创建的以及驻留在内存中的事件处理器少了。这是很重要的一点,这样我们就提高了性能,并降低了崩溃的风险;
    2、在DOM更新后无须重新绑定事件处理器了。如果你的页面是动态生成的,比如说通过Ajax,你不再需要在元素被载入或者卸载的时候来添加或者删除事件处理器了。

    使用中应该注意的问题:
    1、事件管理代码有成为性能瓶颈的风险,所以尽量使它能够短小精悍;
    2、不是所有的事件都能冒泡的。blur、focus、load和unload不能像其它事件一样冒泡。事实上blur和focus可以用事件捕获而非事件冒泡的方法获得(在IE之外的其它浏览器中);
    3、在管理鼠标事件的时候有些需要注意,如果处理mousemove这样的事件的话遇上性能瓶颈的风险就很大,因为mousemove事件触发非常频繁,而且mouseout则因为其怪异的表现而变得很难用事件代理来管理。

    jquery的事件代理:

    现有的主流javascript库的事件代理已经实现了,例如jquery的事件代理方式实现上述功能:

    1
    2
    3
    4
    5
    window.onload = function() {  
    $("#parent-list").delegate("li", "click", function(){
    console.log("you clicked item!", $(this));
    });
    }

    • 点击”Item 1”,输出以下信息:

      1
      you clicked item! [li#post-1, context: li#post-1]
    • 另一种写法:

      1
      2
      3
      4
      5
      6
      window.onload = function() { 
      $('#parent-list').click($.delegate({
      '.quit': function() { console.log("do quit stuff"); },
      '.edit': function() { console.log("do edit stuff"); }
      }));
      }

    感谢您的阅读,有不足之处请在评论为我指出!

    版权声明:本文为博主原创文章,未经博主允许不得转载。本文地址 http://yangyuji.github.io/2015/05/29/javascript-delegation/