JavaScript事件委托,如何处理被点击元素的父元素?

21

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实现。


实际上对你的问题感到困惑,不明白你想要实现什么。 - The Alpha
我总是在这个问题上遇到麻烦...这个链接可能会有所帮助:http://www.quirksmode.org/js/events_order.html - Jeffrey Sweeney
1
@Michal,这似乎不太高效,我在想这是唯一的方法吗? - mowwwalker
2个回答

22

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

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 方法可以帮助您实现此类功能。


我对jQuery进行了一些调查,这是我发现的。 - mowwwalker
谢谢 :) 这正是我需要的。 - Frank Fang

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

完美!那正是我所需要的。谢谢。 - romerompb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接