Какая разница между event.stopPropagation и event.preventDefault?

Они, похоже, делают то же самое... Один современный и старый? Или они поддерживаются разными браузерами?

Когда я обрабатываю события самостоятельно (без фреймворка), я всегда проверяю оба и выполняю оба, если они есть. (Я также return false, но я чувствую, что не работает с событиями, связанными с node.addEventListener).

Так почему же? Должен ли я продолжать проверять оба? Или есть ли разница?

(Я знаю, много вопросов, но все они одинаковы =))

+733
источник поделиться
7 ответов

stopPropagation останавливает всплытие события в цепочке событий.

preventDefault запрещает действие по умолчанию, которое браузер выполняет с этим событием.

Примеры

preventDefault

$("#but").click(function (event) {
  event.preventDefault()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

stopPropagation

$("#but").click(function (event) {
  event.stopPropagation()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

В stopPropagation вызывается только button обработчик кликов, в то время как div обработчик кликов никогда не срабатывает.

Где, как будто вы используете preventDefault, только действие браузера по умолчанию останавливается, но обработчик щелчка div все еще срабатывает.

Ниже приведены некоторые документы по свойствам и методам событий DOM из MDN:

Для IE9 и FF вы можете просто использовать protectDefault & stopPropagation.

Для поддержки IE8 и ниже замените stopPropagation на cancelBubble и замените preventDefault на returnValue

+918
источник

терминология

С quirksmode.org:

Захват событий

Когда вы используете захват событий

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

обработчик события element1 срабатывает первым, обработчик события element2 срабатывает последним.

Событие кипит

Когда вы используете всплывающее событие

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

обработчик события element2 срабатывает первым, обработчик события element1 срабатывает последним.

Любое событие, происходящее в модели событий W3C, сначала фиксируется до достижения целевого элемента, а затем снова всплывает.

                 | |  / \
-----------------| |--| |-----------------
| element1       | |  | |                |
|   -------------| |--| |-----------     |
|   |element2    \ /  | |          |     |
|   --------------------------------     |
|        W3C event model                 |
------------------------------------------

Интерфейс

С w3.org, для захвата событий:

Если захват EventListener желает предотвратить дальнейшую обработку события, он может вызвать метод stopPropagation интерфейса Event. Это предотвратит дальнейшую отправку события, хотя дополнительные EventListeners зарегистрированные на том же уровне иерархии, все еще получат событие. После stopPropagation метода stopPropagation дальнейшие вызовы этого метода не имеют никакого дополнительного эффекта. Если никаких дополнительных захватчиков не существует и stopPropagation не был вызван, событие вызывает соответствующие EventListeners на самой цели.

Для всплытия событий:

Любой обработчик события может решить предотвратить дальнейшее распространение события, вызвав метод stopPropagation интерфейса Event. Если какой-либо EventListener вызывает этот метод, все дополнительные EventListeners на текущем EventTarget будут запущены, но EventTarget прекратятся на этом уровне. Только один вызов stopPropagation требуется, чтобы предотвратить дальнейшее образование пузырьков.

Для отмены мероприятия:

Отмена осуществляется путем вызова метода Event preventDefault. Если один или несколько EventListeners вызовут preventDefault во время любой фазы потока событий, действие по умолчанию будет отменено.

Примеры

В следующих примерах щелчок по гиперссылке в веб-браузере запускает поток событий (слушатели событий выполняются) и целевое действие события по умолчанию (открывается новая вкладка).

HTML:

<div id="a">
  <a id="b" href="http://www.google.com/" target="_blank">Google</a>
</div>
<p id="c"></p>

JavaScript:

var el = document.getElementById("c");

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
}

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
}

function bubblingOnClick1(ev) {
    el.innerHTML += "DIV event bubbling<br>";
}

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
}

// The 3rd parameter useCapture makes the event listener capturing (false by default)
document.getElementById("a").addEventListener("click", capturingOnClick1, true);
document.getElementById("b").addEventListener("click", capturingOnClick2, true);
document.getElementById("a").addEventListener("click", bubblingOnClick1, false);
document.getElementById("b").addEventListener("click", bubblingOnClick2, false);

Пример 1: это приводит к выводу

DIV event capture
A event capture
A event bubbling
DIV event bubbling

Пример 2: добавление stopPropagation() в функцию

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.stopPropagation();
}

результаты на выходе

DIV event capture

Слушатель события предотвратил дальнейшее распространение события вниз и вверх. Однако это не помешало действию по умолчанию (открытие новой вкладки).

Пример 3: добавление stopPropagation() к функции

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
    ev.stopPropagation();
}

или функция

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
    ev.stopPropagation();
}

результаты на выходе

DIV event capture
A event capture
A event bubbling

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

Пример 4: добавление preventDefault() к любой функции, например

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.preventDefault();
}

предотвращает открытие новой вкладки.

+221
источник
другие ответы

Связанные вопросы


Похожие вопросы

вернуть ложь;


return false; делает 3 отдельные вещи, когда вы называете это:

  1. event.preventDefault() - останавливает поведение браузера по умолчанию.
  2. event.stopPropagation() - предотвращает распространение (или " event.stopPropagation() события DOM.
  3. Останавливает выполнение обратного вызова и немедленно возвращается при вызове.

Обратите внимание, что это поведение отличается от обычных (не jQuery) обработчиков событий, в которых, в частности, return false не останавливает всплывающее событие.

preventDefault();


preventDefault(); делает одно: останавливает поведение браузера по умолчанию.

Когда их использовать?


Мы знаем, что они делают, но когда их использовать? Просто это зависит от того, чего вы хотите достичь. Используйте preventDefault(); если вы хотите "просто" предотвратить поведение браузера по умолчанию. Используйте return false; когда вы хотите предотвратить поведение браузера по умолчанию и предотвратить распространение DOM события. В большинстве ситуаций, где вы бы использовали return false; то, что вы действительно хотите, это preventDefault().

Примеры:


Давайте попробуем разобраться с примерами:

Мы увидим чистый пример JAVASCRIPT

Пример 1:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

Запустив приведенный выше код, вы увидите гиперссылку "Нажмите здесь, чтобы перейти на stackoverflow.com". Теперь, если вы сначала нажмете на эту ссылку, вы получите предупреждение JavaScript. Ссылка нажата. Далее вы получите уведомление о нажатии JavaScript, которое будет нажато, и сразу же вы будете перенаправлены на stackoverflow.com.

Пример 2:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

Запустите приведенный выше код, вы увидите гиперссылку "Нажмите здесь, чтобы посетить stackoverflow.com" Теперь, если нажать на эту ссылку, сначала вы получите уведомление Ссылка яваскрипта нажала Далее вы получите уведомление JavaScript ДИВ нажала Далее вы увидите гиперссылку " Нажмите здесь, чтобы перейти на stackoverflow.com ", замененный текстом" Событие Click предотвращено ", и вы не будете перенаправлены на stackoverflow.com. Это происходит из-за метода event.preventDefault(), который мы использовали для предотвращения срабатывания щелчка по умолчанию.

Пример 3:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

На этот раз, если вы нажмете на ссылку, функция executeParent() не будет вызвана, и вы не получите уведомление о нажатии JavaScript. Это связано с тем, что мы предотвратили распространение на родительский div с помощью метода event.stopPropagation(). Далее вы увидите гиперссылку "Нажмите здесь, чтобы посетить stackoverflow.com", замененную текстом "Событие Click будет выполнено", и вы сразу же будете перенаправлены на stackoverflow.com. Это потому, что мы не предотвратили срабатывание щелчка по умолчанию на этот раз с помощью метода event.preventDefault().

Пример 4:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

Если вы нажмете на ссылку, функция executeParent() не будет вызвана, и вы не получите предупреждение javascript. Это связано с тем, что мы предотвратили распространение на родительский div с помощью метода event.stopPropagation(). Далее вы увидите гиперссылку "Нажмите здесь, чтобы посетить stackoverflow.com", замененную текстом "Событие клика запрещено", и вы не будете перенаправлены на stackoverflow.com. Это потому, что мы предотвратили срабатывание щелчка по умолчанию на этот раз с помощью метода event.preventDefault().

Пример 5:

Для возврата false у меня есть три примера, и все, кажется, делают одно и то же (просто возвращают false), но на самом деле результаты совершенно разные. Вот что на самом деле происходит в каждом из вышеперечисленных.

случаи:

  1. Возврат false из встроенного обработчика событий предотвращает переход браузера по адресу ссылки, но не останавливает распространение события через DOM.
  2. Возвращение false из обработчика событий jQuery не позволяет браузеру перейти на адрес ссылки и останавливает распространение события через DOM.
  3. Возвращение false из обычного обработчика событий DOM абсолютно ничего не делает.

Увидим все три примера.

  1. Встроенный возврат false.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='return false'>Click here to visit stackoverflow.com</a>
</div>
<script>
  var link = document.querySelector('a');

  link.addEventListener('click', function() {
    event.currentTarget.innerHTML = 'Click event prevented using inline html'
    alert('Link Clicked');
  });


  function executeParent() {
    alert('Div Clicked');
  }
</script>
  1. Возвращает false из обработчика событий jQuery.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <a href='https://stackoverflow.com'>Click here to visit stackoverflow.com</a>
</div>
<script>
  $('a').click(function(event) {
    alert('Link Clicked');
    $('a').text('Click event prevented using return FALSE');
    $('a').contents().unwrap();
    return false;
  });
  $('div').click(function(event) {
    alert('Div clicked');
  });
</script>
  1. Возвращает false из обычного обработчика событий DOM.

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
    return false
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

Надеюсь, эти примеры понятны. Попробуйте выполнить все эти примеры в html файле, чтобы увидеть, как они работают.

+59
источник

Это цитата из здесь

event.preventDefault

Метод preventDefault не позволяет событию выполнять свои функции по умолчанию. Например, вы должны использовать preventDefault для элемента A, чтобы не нажимать на этот элемент, оставляя текущую страницу:

//clicking the link will *not* allow the user to leave the page 
myChildElement.onclick = function(e) { 
    e.preventDefault(); 
    console.log('brick me!'); 
};

//clicking the parent node will run the following console statement because event propagation occurs
logo.parentNode.onclick = function(e) { 
    console.log('you bricked my child!'); 
};

В то время как функциональность элемента по умолчанию блокируется, событие продолжает пузыриться в DOM.

event.stopPropagation

Второй метод stopPropagation позволяет использовать функциональные возможности по умолчанию, но предотвращает распространение события:

//clicking the element will allow the default action to occur but propagation will be stopped...
myChildElement.onclick = function(e) { 
    e.stopPropagation();
    console.log('prop stop! no bubbles!'); 
};

//since propagation was stopped by the child element onClick, this message will never be seen!
myChildElement.parentNode.onclick = function(e) { 
    console.log('you will never see this message!'); 
};

stopPropagation эффективно останавливает родительские элементы от знания о данном событии на его дочернем элементе.

В то время как простой метод остановки позволяет нам быстро обрабатывать события, это важно подумать о том, что именно вы хотите совершить с пузыриться. Я бы поспорил, что все, что действительно хочет разработчик, - preventDefault 90% времени! Неправильно "прекращение" события может привести к многочисленные проблемы по линии; ваши плагины могут не работать, и ваши сторонние плагины могут быть замаскированы. Или еще хуже - ваш код нарушает другие функции на сайте.

+16
источник

event.preventDefault(); Остановка действия элемента по умолчанию.

event.stopPropagation(); Предотвращает появление пузырьков в дереве DOM, предотвращая уведомление родительских обработчиков о событии.

Например, если есть ссылка с методом кликов, прикрепленная внутри DIV или FORM, которая также имеет прикрепленный метод щелчка, это предотвратит запуск метода DIV или FORM.

+1
источник

Событие. preventDefault- останавливает поведение браузера по умолчанию. Теперь перейдем к поведению браузера по умолчанию. Предположим, у вас есть тег привязки, у него есть атрибут href, и этот тег привязки вложен в тег div, который получил событие click. Поведение по умолчанию тега привязки происходит при нажатии на тег привязки, по которому он должен перемещаться, но в случае event.preventDefault он останавливает навигацию. Но это никогда не останавливает пузыри события или эскалации события, т.е.

<div class="container">
 <a href="#" class="element">Click Me!</a>
</div>

$('.container').on('click', function(e) {
 console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  console.log('element was clicked');
});

Результат будет

"элемент был нажат"

"контейнер был нажат"

Теперь event.StopPropation останавливает всплывание события или эскалацию события. Теперь с приведенным выше примером

$('.container').on('click', function(e) {
  console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  e.stopPropagation(); // Now the event won't bubble up
 console.log('element was clicked');
});

Результат будет

"элемент был нажат"

Для получения дополнительной информации обратитесь к этой ссылке https://codeplanet.io/preventDefault-vs-stoppropagation-vs-stopimmediatepropagation/

+1
источник

$("#but").click(function(event){
console.log("hello");
  event.preventDefault();
 });


$("#foo").click(function(){
 alert("parent click event fired !");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>
-3
источник

Посмотрите другие вопросы по меткам или Задайте вопрос