Может ли обработчик событий предка остановить распространение одного из событий его дочернего элемента?

Я надеюсь, что кто-то может помочь мне понять, почему приведенный ниже сценарий терпит неудачу. У меня есть родительский тег ul с обработчиком событий, который обуславливает данный потомок элемента li в другом теге ul, вложенном в него. Разметка:

<ul id="outerUL">
    <li>LIST ITEM 1</li>
    <li>LIST ITEM 2</li>
    <li>
        <ul id="innerUL">
            <li>LIST ITEM 3</li>
            <li>LIST ITEM 4</li>
            <li>
                <ul id="inMostUL">
                    <li>LIST ITEM 5</li>
                    <li>LIST ITEM 6</li><!-- we condition for this element -->
                    <li>LIST ITEM 7</li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

Javascript: (кажется, что условный .stopPropagation() в вызове предка терпит неудачу...)

var outerMostUL = document.getElementById("outerUL");
outerMostUL.addEventListener('click', 
    function(e){

        if(e.target.innerHTML === "LIST ITEM 6"){
           e.stopPropagation();
           alert("you clicked LIST ITEM 6. Event travel stops.");
           // return; // a return WILL work
        }

     // below runs if propagation continues...
     alert("outerMostUL event handler fired!");

    },
    false);

Теперь, если я решу ввести сдержанный вызов .addEventListener() для этого тега li, .stopPropagation() будет работать, как и ожидалось, например:

// A discreet event handler does work
var inMostUL = document.getElementById("inMostUL");
inMostUL.children[1].addEventListener('click', function(e){

    e.stopPropagation();
    alert("The descendent event fires, but stops now.");

});

Итак, мой вопрос: СЛЕДУЕТ ли вам использовать условие в обработчике предка для данного e.target и остановить распространение его события, если включено всплытие? Кажется, что у элемента должен быть свой собственный обработчик, связанный с инициированием события, но, возможно, я путаю распространяющееся событие, перемещающееся по цепочке предков, с фактическим добавлением прослушивателя событий с помощью этого метода. Любой легкий пролив будет принят с благодарностью. Я просто пытаюсь осмыслить обработку событий js на простых примерах. Спасибо за любое рассмотрение этого.


person JF Sebastian    schedule 09.01.2014    source источник


Ответы (1)


Распространение всплывающих событий можно остановить с помощью e.stopPropagation() в любой точке цепочки предков, и это остановит дальнейшее распространение события до других предков.

И нет проблем с остановкой распространения условно только при определенных обстоятельствах.


Я думаю, что часть вашей путаницы связана только с вашей функцией javascript, а не с распространением. В этом коде:

var outerMostUL = document.getElementById("outerUL");
outerMostUL.addEventListener('click', function(e){
   if(e.target.innerHTML === "LIST ITEM 6"){
       e.stopPropagation();
       alert("you clicked LIST ITEM 6. Event travel stops.");
   }
   // below runs ALWAYS, regardless of the result of the previous "if" statement
   alert("outerMostUL event handler fired!");
}, false);

Второе предупреждение происходит без оператора return НЕ из-за распространения, а только потому, что ваша функция javascript продолжает выполняться после условного блока if. Это не имеет ничего общего с распространением, а просто с программным потоком javascript. Если вы добавите оператор return, вы преждевременно завершите обратный вызов обработчика событий, поэтому остальная его часть не будет выполнена. Без оператора return выполнение этой функции продолжается после блока if независимо от того, выполняется оператор if или нет.


Чтобы концептуально понять распространение событий, просто подумайте о фрагменте кода в браузере, который инициирует всплывающее всплывающее окно. Это событие сначала отправляется обработчику событий целевого объекта, и если распространение там не отменено, оно затем отправляется следующему предку, и если там распространение не отменено, оно затем отправляется вверх по цепочке предков, пока не будет доходит до объекта document или до тех пор, пока распространение не будет отменено.


Кроме того, имейте в виду, что если вы не используете кросс-платформенную библиотеку, такую ​​как jQuery, и хотите поддерживать более старые версии IE, остановка распространения работает иначе в этих более старых версиях IE.

person jfriend00    schedule 09.01.2014
comment
Добавьте e.cancelBubble = true; для более старой поддержки IE, если только вы не используете jQuery, и в этом случае jQuery сделает это за вас. - person crush; 10.01.2014