Javascript事件委托,处理被点击元素的父母?

时间:2012-03-28 19:46:22

标签: javascript events javascript-events event-handling delegation

http://jsfiddle.net/walkerneo/QqkkA/

我在这里看到很多问题要么在javascript中询问或回答事件委托,但是我还没有看到如何将事件委托用于不会成为目标的元素。点击事件。

例如:

HTML:

<ul>
    <li><div class="d"></div></li>
    <li><div class="d"></div></li>
    <li><div class="d"></div></li>
    <li><div class="d"></div></li>
    <li><div class="d"></div></li>
    <li><div class="d"></div></li>
</ul>​

CSS:

ul{
    padding:20px;
}
li{
    margin-left:30px;
    margin-bottom:10px;
    border:1px solid black;

}
.d{
    padding:10px;
    background:gray;
}
​

如果我想在点击时添加点击事件来处理li元素,该怎么办?如果我将事件处理程序附加到ul元素,则div将始终是目标元素。除了在点击函数中检查目标元素的每个父元素之外,我该如何实现呢?

编辑:

我想使用事件委托而不是:

var lis = document.getElementsByTagName('li');
for(var i=0;i<lis.length;i++){
    lis[i].onclick = function(){};
}

但如果我这样做:

document.getElementsByTagName('ul')[0].addEventListener('click',function(e){

    // e.target is going to be the div, not the li
    if(e.target.tagName=='LI'){

    } 
},false);

编辑:我对如何使用Javascript库不感兴趣,我对他们是如何做到以及如何使用纯js感兴趣。

2 个答案:

答案 0 :(得分:15)

这是解决问题的一种方法:

var list = document.getElementsByTagName('ul')[0]

list.addEventListener('click', function(e){
  var el = e.target
  // walk up the tree until we find a LI item
  while (el && el.tagName !== 'LI') {
     el = el.parentNode
  }
  console.log('item clicked', el)
}, false)

这是过度简化的,循环将继续向上通过UL元素。有关更完整的示例,请参阅rye/events中的实现。

Element.matchesNode.containsNode.compareDocumentPosition方法可以帮助您实现此类功能。

答案 1 :(得分:1)

现在有一个名为closest的元素的方法,它正是这样做的。它将CSS选择器作为参数,并找到最接近的匹配祖先,它可以是元素本身。它的所有当前版本的桌面浏览器support,但一般来说它还没有准备好用于生产。上面链接的MDN页面包含一个polyfill。