В чем разница между event.stopPropagation и event.preventDefault? - PullRequest
715 голосов
/ 11 мая 2011

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

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

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

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

Ответы [ 7 ]

899 голосов
/ 11 мая 2011

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

215 голосов
/ 30 мая 2014

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

С 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 не был вызван, событие вызывает присваивать EventListeners самой цели.

Для всплывающих событий :

Любой обработчик событий может предпочесть предотвратить дальнейшее распространение события вызов метода stopPropagation интерфейса Event. Если есть EventListener вызывает этот метод, все дополнительные EventListeners на ток 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();
}

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

57 голосов
/ 27 мая 2015

return false;


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

  1. event.preventDefault() - останавливает поведение браузера по умолчанию.
  2. 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 10 Теперь, если вы сначала нажмете на эту ссылку, вы получите предупреждение javascript Ссылка нажата Далее вы получите javascript alert div Нажмите , и вы сразу же будете перенаправлены на 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 Ссылка нажата Далее вы получите JavaScript alert div Нажмите Далее вы увидите гиперссылку ‘Нажмите здесь, чтобы Посетите stackoverflow.com ‘заменено текстом‘ Событие клика запрещено ‘ и вы будете не перенаправлены на 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 Кликнул этот раз. Это связано с тем, что мы предотвратили распространение на родительский div с использованием метода event.stopPropagation (). Далее вы увидите гиперссылка ‘Нажмите здесь, чтобы посетить stackoverflow.com‘ заменены текстом ‘Событие клика будет выполнено‘ и сразу вы будете перенаправлен на 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. Inline return 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-файле, чтобы увидеть, как они работают.

16 голосов
/ 25 марта 2014

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

event.preventDefault

Метод protectDefault предотвращает выполнение событием своих функций по умолчанию. Например, вы использовали бы protectDefault для элемента 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's onClick, this message will never be seen!
myChildElement.parentNode.onclick = function(e) { 
    console.log('you will never see this message!'); 
};

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

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

1 голос
/ 08 августа 2018

Event.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 голос
/ 06 мая 2015

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

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

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

0 голосов
/ 10 сентября 2017

$("#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>
...