Подскажите пожалуйста, почему не работает функция 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>
Я полагаю это ответ на ваш вопрос?
Отвечает ли это на ваш вопрос? В чем разница между event.stopPropagation и event.preventDefault?
@ChrisG не работает
почему функция 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: Действительно, я вижу ваш код. Я даже протестировал его и скопировал в этот ответ. Затем я добавил родительский элемент (div.outer), чтобы продемонстрировать, что делает stopPropagation() и как он работает. В вашем коде нет обработчика событий выше по иерархии DOM для наблюдения, поэтому нет заметной разницы между событием, которое перестало распространяться, и событием, которое не распространялось. Я добавил такой элемент, чтобы можно было наблюдать разницу.
Мне не нужно предупреждение(1);
@Vans: я обновил ответ. Хотя похоже, что другой ответ на обновленный вопрос также касается новой проблемы.
Есть ли способ сделать это с помощью jquery? Я использую этот обработчик, потому что элементы '.el' добавляются с добавлением.
@Vans: обновил ответ. Хотя нет никакой гарантии, что это также коснется всего, что вы собираетесь редактировать в следующем вопросе...
Новые элементы могут появиться позже, после загрузки страницы.
@Vans: Действительно. И я подозреваю, что только с jQuery вам нужно будет прикрепить обработчики click непосредственно к этим добавленным элементам, что, конечно, должно произойти после их добавления, как в самом последнем примере в этом ответе. Можно углубиться в захват событий, как показано в этом ответе, используя собственные функции, но если я что-то не упустил, я не вижу возможности в jQuery сделать это. То, что у вас есть в проблеме, представляет собой смесь jQuery и нативной функциональности, поэтому элегантное решение, вероятно, будет включать то же самое.
Понял. Спасибо за ответ. Буду глобально менять код, чтобы была одна обработка.
Во-первых, вы сделали опечатку. 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 - я отсылаю вас к последнему предложению перед примером кода этого ответа.
Это не меняет этот ответ.
Этот ответ не работает, потому что это должно быть сделано в jquery.
JQuery не может этого сделать. (И требовать jQuery, когда это тривиально сделать с помощью встроенных методов, предоставляемых браузером, глупо.)
Все можно сделать без использования jquery.
Есть ли другой способ использовать обработчик новых элементов с помощью jquery?
Понял. Спасибо за ответ. Буду глобально менять код, чтобы была одна обработка.
Это также не препятствует немедленному распространению на другие обработчики событий. Если вы хотите остановить их, см. stopImmediatePropagation(). это то, что говорится в документации