1

我正在尝试使用以下代码实现事件委托:

<html>
<head>
<script>
document.addEventListener('click', function(e){
    alert(e.target.className);
}, false);
</script>
</head>
<body>
<ul class="list">
    <li class="item">A</li>
    <li class="item">B</li>
    <li class="item">C</li>
    <li class="item">D</li>
</ul>
</body>
</html>

我希望事件冒泡,这样当我单击一个<li>项目时,会显示一个警报item,然后显示另一个警报list。但是这段代码只给出了警报item。如何修改它以使事件冒泡?

4

5 回答 5

1

当您在document对象上绑定点击处理程序时,您不能期望它会被多次调用。它只会被调用一次(在document对象上)。

顺便说一句,该事件确实会在 DOM 树中冒泡。如果没有,它就不会到达document对象,您也不会看到任何警报框。

因此,事件在 LI 元素处触发,然后一直冒泡到document对象,在该对象处调用单击处理程序。

顺便说一句,通常您不会一直委托给document对象,而是委托给最近的共同祖先。例如,如果你想处理对 LI 元素的点击,你可以委托给 UL 元素:

var list = document.getElementsByClassName( 'list' )[0];    

list.addEventListener( 'click', function ( e ) {
    var item = e.target;

    // handle item click
}, false );

现场演示:http: //jsfiddle.net/rCVfq/

于 2012-02-03T19:35:48.630 回答
1

您需要为列表添加事件以提醒它。事件被父对象捕获,但没有事件绑定到它们,因此它不会发出警报。您需要为所有对象添加事件以提醒它。

于 2012-02-03T19:40:05.410 回答
1

事件回调只触发一次,但不代表事件不冒泡。回调仅在元素监听事件时执行。

如果您真的希望警报一直触发到祖先,在您的回调中,为祖先添加警报。您不必为所有祖先添加侦听器,这会导致消耗更多内存。

于 2012-02-03T19:47:31.683 回答
1

我刚刚发布了一个小型事件委托库,以便更轻松地执行此类操作。在http://craig.is/riding/gators查看

你可以做

Gator(document).on('click', 'li', function() { alert('li clicked!'); });
Gator(document).on('click', 'ul', function() { alert('ul clicked!'); });

这会将单击处理程序绑定到文档并相应地调度事件。

当您单击时它们都会触发,li除非您停止传播。

于 2012-11-28T19:02:50.703 回答
0

您可以使用一些循环方法来调用这两个警报:

var list = document.getElementsByClassName('list')[0];
list.addEventListener("click", function (e) {
   var target = e.target;
   while (target !== list) {
      switch(target.nodeName) {
          case "LI": //alert('li clicked!')
          break;
          case "UL": //alert('ul clicked!')
          break;
      }
      target = target.parentNode;
   }
});
于 2014-01-03T06:32:01.620 回答