E.stopPropagation() при событии клика

Подскажите пожалуйста, почему не работает функция e.stopPropagation()?

$(document).ready(function() {
  var el = '<div class = "el" onclick = "alert(1);"><div class = "stop">X</div>Click</div>';
  $("body").append(el);
})
$(document).on("click", ".stop", function(e) {
  e.stopPropagation();
  e.preventDefault();
  alert(2);
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
</body>

Это также не препятствует немедленному распространению на другие обработчики событий. Если вы хотите остановить их, см. stopImmediatePropagation(). это то, что говорится в документации

Chris G 23.02.2023 12:54

Я полагаю это ответ на ваш вопрос?

Miss Skooter 23.02.2023 12:54

Отвечает ли это на ваш вопрос? В чем разница между event.stopPropagation и event.preventDefault?

Miss Skooter 23.02.2023 12:57

@ChrisG не работает

Vans 23.02.2023 12:58
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
Интервьюер: Почему &apos;[] instanceof Object&apos; возвращает &quot;true&quot;?
Интервьюер: Почему '[] instanceof Object' возвращает "true"?
Все мы знаем, что [] instanceof Array возвращает true, но почему [] instanceof Object тоже возвращает true?
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) и как оно работает с ReactJS
Абстрактное синтаксическое дерево (AST) - это древовидная структура данных, которая представляет структуру и иерархию исходного кода на языке...
1
4
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

почему функция e.stopPropagation() не работает?

Это работает. Наблюдать:

$(document).on("click", ".outer", function(e) {
  alert(3);
});

$(document).on("click", ".el", function(e) {
  e.stopPropagation();
  alert(2);
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "outer">
  <div class = "el" onclick = "alert(1)";>Click</div>
</div>

В вашем коде действительно останавливается распространение событий. Однако в дереве DOM нет дополнительных обработчиков событий, поэтому в первую очередь не нужно наблюдать за распространением. У вас есть два отдельных события click, обрабатывающих один и тот же элемент, оба из которых обрабатываются независимо.

В показанном здесь примере родительский элемент (div.outer) имеет обработчик событий, и распространение останавливается до того, как оно достигает этого обработчика. Не останавливая распространение, вы увидите, что вызывается обработчик событий:

$(document).on("click", ".outer", function(e) {
  alert(3);
});

$(document).on("click", ".el", function(e) {
  alert(2);
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "outer">
  <div class = "el" onclick = "alert(1)";>Click</div>
</div>

Возможно, вы ищете stopImmediatePropagation() вместо этого? Это предотвратит вызов дополнительных обработчиков событий для того же элемента. Например:

$(document).on("click", ".el", function(e) {
  e.stopImmediatePropagation();
  alert(2);
});

$(document).on("click", ".el", function(e) {
  e.stopImmediatePropagation();
  alert(3);
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "el" onclick = "alert(1)";>Click</div>

В этом случае второй обработчик click целевого элемента остановил дальнейшие click обработчики того же элемента от обработки. Обратите внимание, что это не влияет на первый обработчик click, который к тому времени уже был вызван.


Обновлено: ваш обновленный код демонстрирует немного другую проблему. (Что скрывалось в исходном коде из-за исходной проблемы, рассмотренной выше.)

Обратите внимание, как вы подключаете обработчик событий jQuery. К какому объекту DOM вы его прикрепляете?... document. Который находится намного выше в иерархии DOM и не достигается до тех пор, пока родительский элемент уже не обработал свой встроенный обработчик click.

Если вы прикрепите обработчик click непосредственно к элементу, вы увидите разницу:

$(".stop").on("click", function(e) {
  e.stopPropagation();
  alert(2);
});
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class = "el" onclick = "alert(1)">
  <div class = "stop">X</div>
  Click
</div>

Еще одно редактирование для текущей движущейся цели...

Вы по-прежнему сталкиваетесь с той же проблемой. Один обработчик кликов находится на самом элементе, другой — на объекте document. Последнее не будет обработано раньше первого.

Добавление элементов в DOM постфактум может действительно немного усложнить ситуацию в этом случае, и вам может понадобиться прикрепить обработчик кликов к самим элементам после их добавления. Например, это останавливает распространение:

$(document).ready(function() {
  var el = '<div class = "el" onclick = "alert(1);"><div class = "stop">X</div>Click</div>';
  $("body").append(el);
  
  $(".stop").on("click", function(e) {
    e.stopPropagation();
    alert(2);
  });
})
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
</body>

Ключевое отличие здесь заключается в том, что обработчик jQuery click не привязан к document и не полагается на делегирование/распространение событий в первую очередь. Он прикрепляется непосредственно к целевому элементу и поэтому должен быть присоединен после добавления элемента в DOM.

Что это за новые элементы? Разве ты не видишь мой код?

Vans 23.02.2023 12:57

@Vans: Действительно, я вижу ваш код. Я даже протестировал его и скопировал в этот ответ. Затем я добавил родительский элемент (div.outer), чтобы продемонстрировать, что делает stopPropagation() и как он работает. В вашем коде нет обработчика событий выше по иерархии DOM для наблюдения, поэтому нет заметной разницы между событием, которое перестало распространяться, и событием, которое не распространялось. Я добавил такой элемент, чтобы можно было наблюдать разницу.

David 23.02.2023 12:59

Мне не нужно предупреждение(1);

Vans 23.02.2023 13:04

@Vans: я обновил ответ. Хотя похоже, что другой ответ на обновленный вопрос также касается новой проблемы.

David 23.02.2023 13:19

Есть ли способ сделать это с помощью jquery? Я использую этот обработчик, потому что элементы '.el' добавляются с добавлением.

Vans 23.02.2023 13:21

@Vans: обновил ответ. Хотя нет никакой гарантии, что это также коснется всего, что вы собираетесь редактировать в следующем вопросе...

David 23.02.2023 13:34

Новые элементы могут появиться позже, после загрузки страницы.

Vans 23.02.2023 13:37

@Vans: Действительно. И я подозреваю, что только с jQuery вам нужно будет прикрепить обработчики click непосредственно к этим добавленным элементам, что, конечно, должно произойти после их добавления, как в самом последнем примере в этом ответе. Можно углубиться в захват событий, как показано в этом ответе, используя собственные функции, но если я что-то не упустил, я не вижу возможности в jQuery сделать это. То, что у вас есть в проблеме, представляет собой смесь jQuery и нативной функциональности, поэтому элегантное решение, вероятно, будет включать то же самое.

David 23.02.2023 13:45

Понял. Спасибо за ответ. Буду глобально менять код, чтобы была одна обработка.

Vans 23.02.2023 13:55
Ответ принят как подходящий

Во-первых, вы сделали опечатку. class содержит только 2 s.

Кроме того, событие начинается с элемента div, по которому вы щелкаете. Затем он распространяется на div с атрибутом onclick (запуская его), затем продолжается вверх по DOM, пока не столкнется с объектом document и не вызовет обработчик события, связанный с jQuery, в этот момент stopPropagation вызывается и останавливается.

Если вы хотите предотвратить срабатывание атрибута onclick, вам нужно обработать событие в фазе захвата. Я не думаю, что jQuery поддерживает это, поэтому вместо этого вам нужно использовать собственный DOM.

document.addEventListener("click", function(e) {
  if (!e.target.closest(".stop")) return;
  e.stopPropagation();
  alert(2);
}, {
  capture: true
});
<div class = "el" onclick = "alert(1)" ;>
  <div class = "stop">X</div>
  Click
</div>

Есть ли способ сделать это с помощью jquery? Я использую этот обработчик, потому что элементы '.el' добавляются с добавлением.

Vans 23.02.2023 13:20

@Vans - я отсылаю вас к последнему предложению перед примером кода этого ответа.

Quentin 23.02.2023 13:21

Это не меняет этот ответ.

Quentin 23.02.2023 13:25

Этот ответ не работает, потому что это должно быть сделано в jquery.

Vans 23.02.2023 13:28

JQuery не может этого сделать. (И требовать jQuery, когда это тривиально сделать с помощью встроенных методов, предоставляемых браузером, глупо.)

Quentin 23.02.2023 13:29

Все можно сделать без использования jquery.

Vans 23.02.2023 13:31

Есть ли другой способ использовать обработчик новых элементов с помощью jquery?

Vans 23.02.2023 13:32

Понял. Спасибо за ответ. Буду глобально менять код, чтобы была одна обработка.

Vans 23.02.2023 13:56

Другие вопросы по теме