3

HTML:

<ul>
    <li>
        <a href="http://wp.pl">wp.pl</a>
    </li>
</ul>

Javascript:

$(document).ready(function() {
    $body = $('body');

    $body.on('click', 'a', function(event) {
        event.preventDefault();
        event.stopPropagation();

        /**
         * Causes the "This also..." never shows, but "Why is..." still appears
         */
        //event.stopImmediatePropagation();

        alert('Should be seen always');
    });

    $body.on('click', 'a', function(event) {
        alert('This also should be seen - same level as "a"');
    });

    $body.on('click', 'li', function() {
        alert('This never shows - and that is ok - because is under "a"');
    });

    $body.find('ul').on('click', 'li', function() {
        alert('Why is this shown?');
    });
});

在这里摆弄:http: //jsfiddle.net/g3PEr/1/

问题是:为什么即使在其子元素具有or的情况下,也会在click被触发的元素上设置事件?find()stopPropagation()stopImmediatePropagation()


请阅读接受的答案及其评论以了解为什么会发生这种情况。

4

3 回答 3

2

如果您在第二个参数中指定"a"or并不重要- 事件处理程序附加到. 选择器所做的唯一一件事就是充当过滤器。当传播路径上没有任何元素与过滤器匹配时,不会触发事件处理程序。就是这样。"li""body""a"

因此,将您的代码视为:

   $body.on('click', function(event) {
        event.preventDefault();
        event.stopPropagation();
    });

    $body.on('click', function(event) {

    });

    $body.on('click', function() {

    });

    $("ul").on('click', function() {

    });

由于冒泡从底部开始,因此"ul"首先触发处理程序。然后是身体处理程序,它们按照事件附加的顺序触发,因为它们都在身体上。

.stopImmediatePropagation()可用于停止传播到同一级别以及任何更高级别的处理程序。

的上层"body"仍然是documentand window(窗口位于所有内容的顶部),但是因为那里没有处理程序,所以您不会观察到它stopPropagation()有任何影响。

另一种解释调用与调用$("body").on( "click", "li", fn );相同的方法:

$("body").on( "click", function(e) {
    var currentTarget = $(e.target).closest("li");
    if( currentTarget.size() > 0 ) {
        e.currentTarget = currentTarget;
        fn.call(currentTarget, e);
    }
});
于 2013-08-12T16:55:10.567 回答
0

您正在使用委托事件注册来注册事件处理程序,它利用事件冒泡来注册事件处理程序意味着当元素中发生事件时,它将冒泡到所有祖先元素,直到它到达文档对象。

在您的情况下,当您单击时a,它会触发元素的单击事件a,然后传播到liul注册了单击处理程序的位置,然后它会被触发,然后到达body,html最后到document您拥有其他单击处理程序的对象已注册,因此这些也会在您停止传播但附加到的事件ul已被触发的地方执行。

关联的li处理程序不会被触发,因为在处理程序中body阻止了传播abody

于 2013-08-12T16:50:08.353 回答
0

您正在使用委托事件侦听器,因此事件处理程序附加到委托目标,而不是后代。

前三个事件绑定到body元素,最后一个事件绑定到ul元素,它是body. 因此,ul元素上的处理程序将首先触发,因为事件尚未冒泡body。一旦事件到达,body传播就会停止(如果a点击了标签)。

于 2013-08-12T16:53:02.227 回答