首页 > js事件委托的问题

js事件委托的问题

代码如下:

<ul>
    <li><a href="#">item1</a></li>
    <li><a href="#">item2</a></li>
    <li><a href="#">item3</a></li>
    <li><a href="#">item4</a></li>
    <li><a href="#">item5</a></li>
</ul>

<script>
    var el = document.querySelector("ul");
    el.addEventListener("click",function(e){
        e.preventDefault();
        var target = e.target;
        if(target.tagName !== "LI") return;
        //if(target.tagName !== "A") return;
        console.log(target.tagName);    //并没有输出 LI,改成 A 后却能输出 A
    }, false)
</script>

请问,为什么事件只冒泡到 a 标签上就结束了?并没有输出 LI?

换个问法:

<ul>
    <li><a href="#">item1</a></li>
</ul>

<script>
    var el = document.querySelector("ul");
    el.addEventListener("click",function(e){
        e.preventDefault();
        var target = e.target;
        console.log(target.tagName);    
    },false)
</script>

我的理解是事件冒泡应该连续的输出 A LI UL ,但是这里只输出了 A,为什么,感觉我好像把事件冒泡理解错了,求解释

或者如何实现一个事件委托?


感谢大家,已经明白了,Event.target 指触发事件的对象,而 Event.currentTarget 指向的是绑定事件处理器的对象

代码稍作改进,这样才算是事件委托嘛:

var el = document.querySelector("ul");
    el.addEventListener("click",function(e){
        e.preventDefault();
        var target = e.target;
        while(target !== e.currentTarget){
            switch (target.nodeName){
                case "A": console.log("A标签点击");
                    break;
                case "LI": console.log("LI标签点击");
                    break;
            }
            target = target.parentNode;
        }
    }, false)

 var el = document.querySelector("ul");
 el.addEventListener("click",function(e){
     console.log(e.target.tagName);
     console.log(e.currentTarget.tagName);
 }, false)

你的事件监听是加在ul元素上的,
那么它作用是当ul下的任何一个子元素触发click事件时,按事件冒泡机制,绑定的事件回调将被触发
event.target指向触发click的元素,event.currentTarget指向绑定事件回调的DOM元素

那么li为什么没有输出呢?因为你没有添加任何监听在li元素上啦~~
咦~~事件冒泡不是会冒泡到li元素上的么?是的,冒泡阶段会触发li上的click事件,但是你对这个事件没兴趣,所以它越过你继续向上冒了;
冒泡是当下级元素被触发事件通知其上级的机制,如果有上级对你的事件感兴趣,那么绑定在其上的事件回调就会被执行;但是并不能修改事件由谁触发的这个事实,这个不容篡改,那么event.target就永远是触发事件的那个DOM元素

我们可以在li元素上添加个事件监听-如下代码,那么现在点击第1个li
将看到 A>LI>A>UL 这就是冒泡~~~~

 var el = document.querySelector("ul");
 el.addEventListener("click",function(e){
     console.log(e.target.tagName);
     console.log(e.currentTarget.tagName);
 }, false)
 var li = document.querySelector("li");
 li.addEventListener("click",function(e){
     console.log(e.target.tagName);
     console.log(e.currentTarget.tagName);
 },false);

事件代理机制中,你需要告诉代理你要监听那个元素或元素的筛选条件,当事件从指定的DOM元素上触发或符合条件的DOM元素上触发时,定义的事件回调就会被触发。是一个判断event.target的过程;
而不需要为每一个元素指定事件回调。


你在 ul 上做的事件监听
event.target 是事件属性可返回事件的目标节点(触发该事件的节点)
所以不可能输出 li。
你这捕获到的事件已经是冒泡到 ul 上的了


这里实际的区别是e.target和e.currentTarget的区别,e.target是实际的触发事件的element,而e.currentTarget是你绑定了handler的element,所以刚才的代码里面e.target是A,但e.currentTarget就是UL了

在 http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-currentTarget 中

currentTarget of type EventTarget, readonly
Used to indicate the EventTarget whose EventListeners are currently being processed. This is particularly useful during capturing and bubblin
target of type EventTarget, readonly
Used to indicate the EventTarget to which the event was originally dispatched.

【热门文章】
【热门文章】