Event.stopPropagation ve event.preventDefault arasındaki fark nedir?


833

Aynı şeyi yapıyorlar gibi görünüyor ...
Biri modern diğeri eski mi? Yoksa farklı tarayıcılar tarafından destekleniyor mu?

Olayları kendim (çerçevesiz) işlediğimde, her zaman ikisini de kontrol eder ve varsa ikisini de yürütürüm. (Ben de return false, ama ekli olaylarla çalışmaz hissim var node.addEventListener).

Peki neden ikisi de? İkisini de kontrol etmeye devam etmeli miyim? Yoksa aslında bir fark var mı?

(Biliyorum, birçok soru, ama hepsi aynı =)

Yanıtlar:


1014

stopPropagation olayın olay zincirini köpürmesini engeller.

preventDefault tarayıcının o olayda yaptığı varsayılan işlemi engeller.

Örnekler

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>

İle stopPropagation, 'tıklama işleyicisi hiçbir zaman tetiklenmezken yalnızca button' tıklama işleyicisi çağrılır .div

Kullandığınız gibi preventDefault, yalnızca tarayıcının varsayılan eylemi durdurulur, ancak div'ın tıklama işleyicisi yine de tetiklenir.

MDN'nin DOM olay özellikleri ve yöntemleriyle ilgili bazı dokümanlar aşağıdadır:

IE9 ve FF için sadece cancelDefault & stopPropagation kullanabilirsiniz.

IE8 desteklemek ve değiştirme düşürmek için stopPropagationbirlikte cancelBubbleve değiştirme preventDefaultilereturnValue


Yani çok farklılar mı? IE'de bunun için iki farklı olay yöntemi var mı? Bu çerçeveler kendi içinde her ikisini de çok garip (bunlar ?? aynı olabilirdi) event.stopO sorun hiç olmadı da tuhaf ... işlevi. Köpürmeyi çok kullanıyorum. Örnek için teşekkürler!
Rudie

@Rudie tarayıcı desteğine yorum yaptı.
Raynos

7
(MSDN belgelerine bakmamanız durumunda) cancelBubbleve returnValueher iki özellik (de ayarlanmalıdır cancelBubble = true;) ve bu preventDefaultve stopPropagationyöntemlerdir (yani çağrılmalıdır preventDefault();)
freefaller

1
@Raynos, sadece bir not: event.stopPropagation () yalnızca olayın olay zincirini patlatmasını değil, aynı zamanda yakalama aşamasında olayın yayılmasını da durdurur ( developer.mozilla.org/en-US/docs/Web/ API / Event / stopPropagation )
Yuci

1
Bir düğmeyi tıklatmak için varsayılan işlemin ne olduğunu bilmek yararlı olacaktır, bu yüzden neden stopDefault()aynı şekilde çalışmadığını açıklayabilirim stopPropagation(). Varsayılan işlem onclickyöntemi çağırmıyorsa nedir?
d512

249

terminoloji

Gönderen quirksmode.org :

Etkinlik yakalama

Etkinlik yakalamayı kullandığınızda

               | |
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 \ / | |
| ------------------------- |
| Etkinlik YAKALAMA |
-----------------------------------

ilk olarak element1 olay işleyicisi tetiklenir, son olarak element2 olay işleyicisi tetiklenir.

Olay köpürme

Olay köpürme kullandığınızda

               / \
--------------- | | -----------------
| element1 | | |
| ----------- | | ----------- |
| | element2 | | | |
| ------------------------- |
| Etkinlik BUBBLING |
-----------------------------------

ilk olarak element2 olay işleyicisi tetiklenir, son olarak element1 olay işleyicisi tetiklenir.

W3C olay modelinde gerçekleşen herhangi bir olay ilk olarak hedef öğeye ulaşana kadar yakalanır ve ardından tekrar kabarır .

                 | | / \
----------------- | | - | | -----------------
| element1 | | | | |
| ------------- | | - | | ----------- |
| | element2 \ / | | | |
| -------------------------------- |
| W3C olay modeli |
------------------------------------------

Arayüz

Gönderen W3.org için, olay yakalama :

Eğer yakalama EventListener, olayın daha fazla işlenmesini önlemek istiyorsa stopPropagation, Eventarabirimin yöntemini çağırabilir . EventListenersAynı hiyerarşi düzeyinde kaydedilen ek etkinlik yine de alınmasına rağmen, bu, etkinliğin daha fazla gönderilmesini önleyecektir . Bir etkinliğin stopPropagation yöntemi çağrıldıktan sonra, bu yönteme yapılan başka çağrıların ek bir etkisi olmaz. Ek yakalayıcı yoksa ve stopPropagationçağrılmadıysa, olay uygun olanı EventListenershedefte tetikler .

İçin olay köpüren :

Herhangi bir olay işleyici stopPropagation, Eventarabirimin yöntemini çağırarak daha fazla olay yayılmasını engellemeyi seçebilir . Herhangi biri EventListenerbu yöntemi çağırırsa EventListeners, akımdaki tüm ek EventTargettetiklenir, ancak bu seviyede kabarcıklanma durur. stopPropagationDaha fazla köpürmeyi önlemek için yalnızca bir çağrı gerekir.

İçin olay iptali :

İptal yöntemi Event' preventDefaultyöntemi kullanılarak gerçekleştirilir. Olay akışının herhangi bir aşamasında bir veya daha fazla EventListenersçağrı yapılırsa preventDefault, varsayılan eylem iptal edilir.

Örnekler

Aşağıdaki örneklerde, web tarayıcısındaki köprüye tıklamak olayın akışını (olay dinleyicileri yürütülür) ve olay hedefinin varsayılan eylemini (yeni bir sekme açılır) tetikler.

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);

Örnek 1 : çıktı ile sonuçlanır

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

Örnek 2 : ilave stopPropagation()fonksiyona

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

sonuç çıktı

DIV event capture

Olay dinleyicisi, olayın aşağı ve yukarı doğru ilerlemesini engelledi. Ancak, varsayılan eylemi engellemedi (yeni bir sekme açma).

Örnek 3 : ilave stopPropagation()fonksiyona

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

veya işlev

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

sonuç çıktı

DIV event capture
A event capture
A event bubbling

Bunun nedeni, her iki olay dinleyicisinin de aynı olay hedefine kayıtlı olmasıdır. Olay dinleyicileri, olayın yukarı doğru yayılmasını engelledi. Ancak, varsayılan işlemi engellemediler (yeni bir sekme açma).

Örnek 4 : preventDefault()Herhangi bir işleve ekleme , örneğin

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

yeni bir sekmenin açılmasını engeller.


23
Yakalama ve köpürme arasındaki derin ayrım için teşekkürler, diğer cevap sadece jQuery endişelerini ele alıyor.
floribon

@floribon, cevabı için raynos'u rahatsız etmek gibi bir niyetiniz olmadığını söylüyor.
Mahi

3
@Mahi ne? Sadece gerçekleri söylüyorum, kabul edilen cevap OP tarafından varsayılmayan jQuery kullanıyor, bu yüzden benim için gerçek cevap değil. Şimdi bu sadece teknik bir gerçektir, kişisel bir şey ve hiç kimse rahatsız edilmez.
floribon

2
Cevabınız çok sistematik ve neler olduğunu güzel bir şekilde gösteriyor. Başlangıçta sizi rahatsız etmek ve cevabınızda bazı değişiklikler yapmak istemedim, çünkü bunun netlik için biraz geliştirilebileceğini düşünüyorum. Bu cevap olay modelini yeni başlayanlara açıklıyor ve böylelikle yeni başlayanlara verebileceğimiz her türlü yardımın çok yol kat ettiğini düşünüyorum. Düzenleme önerim, katılmadığım genel argümanlar tarafından reddedildi . @Ashkan, bu küçük değişikliklerin cevabı geliştirmeye yardımcı olabileceğini düşünüyorsanız, lütfen bunları ekleyin.
mucaho

68

yanlış döndür;


return false; aradığınızda 3 ayrı şey yapar:

  1. event.preventDefault() - Tarayıcıların varsayılan davranışını durdurur.
  2. event.stopPropagation() - Olayın DOM'u yaymasını (veya “kabarmasını”) önler.
  3. Geri arama işlemini durdurur ve çağrıldığında hemen geri döner.

Bu davranışın normalde (jQuery olmayan) olay işleyicilerinden farklı olduğunu unutmayın; return falseburada olay, köpürmeyi durdurmaz.

preventDefault ();


preventDefault(); bir şey yapar: Tarayıcıların varsayılan davranışını durdurur.

Ne zaman kullanılır?


Ne yaptıklarını ama ne zaman kullanacaklarını biliyoruz? Sadece neyi başarmak istediğinize bağlıdır. preventDefault();Varsayılan tarayıcı davranışını "önlemek" istiyorsanız kullanın . Return false kullanın; varsayılan tarayıcı davranışını önlemek ve olayın DOM'yi yaymasını önlemek istediğinizde. Çoğu durumda false değerini döndüreceğiniz durumlarda; gerçekten istediğin şeypreventDefault() .

Örnekler:


Örneklerle anlamaya çalışalım:

Saf JAVASCRIPT örneğini göreceğiz

Örnek 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>

Yukarıdaki kodu çalıştırın ' Şimdi stackoverflow.com ziyaret etmek için buraya tıklayın' köprüsünü göreceksiniz. İlk önce bu bağlantıyı tıklarsanız javascript uyarısı alırsınız Bağlantı Tıklatıldı Sonra javascript uyarı div'ı alırsınız Tıklandı ve hemen yönlendirileceksiniz stackoverflow.com.

Örnek 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>

Yukarıdaki kodu çalıştırın 'Şimdi stackoverflow.com ziyaret etmek için buraya tıklayın' köprüsünü göreceksiniz. İlk önce bu bağlantıyı tıklarsanız javascript uyarısı alırsınız Link Clicked Next javascript alert div alacaksınız Clicked Next köprüyü göreceksiniz ' stackoverflow.com' metnin yerini 'ziyaret etmek için buraya tıklayın olayı engelledi' ve edecektir tıklayın değil stackoverflow.com yönlendirilecektir. Bunun nedeni, varsayılan tıklama eyleminin tetiklenmesini önlemek için kullandığımız event.preventDefault () yöntemidir.

Örnek 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>

Bu kez Bağla'yı tıklatırsanız executeParent () işlevi çağrılmaz ve javascript uyarısı almazsınız div Bu sefer tıklandı . Bunun nedeni event.stopPropagation () yöntemini kullanarak üst div öğesinin yayılmasını önlemememizdir. Ardından, 'Click olayı yürütülecek' metniyle değiştirilen 'stackoverflow.com'u ziyaret etmek için buraya tıklayın' köprüsünü göreceksiniz ve hemen stackoverflow.com'a yönlendirileceksiniz. Bunun nedeni, event.preventDefault () yöntemini kullanarak varsayılan tıklama eyleminin bu kez tetiklenmesini engellemememizdir.

Örnek 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>

Bağlantıyı tıklatırsanız, executeParent () işlevi çağrılmaz ve javascript uyarısı almazsınız. Bunun nedeni event.stopPropagation () yöntemini kullanarak üst div öğesinin yayılmasını önlemememizdir. Daha sonra, 'Tıklama etkinliği engellendi' metniyle değiştirilen 'stackoverflow.com'u ziyaret etmek için buraya tıklayın' köprüsünü göreceksiniz ve stackoverflow.com'a yönlendirilmeyeceksiniz. Bunun nedeni, event.preventDefault () yöntemini kullanarak varsayılan tıklama eyleminin bu kez tetiklenmesini önlememizdir.

Örnek 5:

Dönüş yanlış için üç örneğim var ve hepsi aynı şeyi yapıyor gibi görünüyor (sadece yanlış dönen), ama gerçekte sonuçlar oldukça farklı. Yukarıdakilerin her birinde gerçekte olan şey.

durumlar:

  1. Geri dönen sahte bir satır içi olay işleyicisinden bağlantı adresine giderek tarayıcının engeller, ancak DOM ile yayılmakta gelen olay durdurmaz.
  2. Geri dönen false bir jQuery olay işleyicisinden bağlantı adresine giderek tarayıcının engeller ve DOM ile yayılmakta gelen olay durdurur.
  3. Normal bir DOM olay işleyicisinden false döndürmek kesinlikle hiçbir şey yapmaz.

Üç örneği de göreceğiz.

  1. Satır içi dönüş yanlış.

<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. Geri dönen false bir jQuery olay işleyicisinden.

<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. Normal bir DOM olay işleyicisinden false döndürülüyor.

<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>

Umarım bu örnekler açıktır. Nasıl çalıştıklarını görmek için tüm bu örnekleri bir html dosyasında çalıştırmayı deneyin.


1
İyi örnekler, ancak jQuery olmadan daha da iyi olurdu, çünkü jQuery olay nesnesini taklit eder, bu yüzden teknik olarak farklıdır.
Rudie

1
@Rudie Cevabımı güncelledim ve jquery'yi ondan kaldırdım ve ayrıca dönüş yanlışına örnek ekledim.
Keval Bhatt

17

Buradan alıntı

event.preventDefault

PreventDefault yöntemi, bir olayın varsayılan işlevselliğini gerçekleştirmesini önler. Örneğin, o öğenin geçerli sayfadan ayrılmasını engellemek için bir A öğesindeki preventDefault öğesini kullanırsınız:

//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!'); 
};

Öğenin varsayılan işlevselliği oluştururken, etkinlik DOM'u patlatmaya devam eder.

Event.stopPropagation

İkinci yöntem olan stopPropagation, olayın varsayılan işlevselliğinin gerçekleşmesine izin verir, ancak olayın yayılmasını önler:

//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, üst öğelerin çocuğundaki belirli bir olay hakkında bilgi sahibi olmasını etkili bir şekilde durdurur.

Basit bir durdurma yöntemi olayları hızlı bir şekilde ele almamıza izin verirken, köpürme ile tam olarak ne olmak istediğinizi düşünmek önemlidir. Bir geliştiricinin gerçekten istediği şeylerin önlenmesi olduğundan emin olabilirimVarsayılan% 90! Bir olayı yanlış bir şekilde "durdurmak", hat boyunca sayısız sıkıntıya neden olabilir; eklentileriniz çalışmayabilir ve üçüncü taraf eklentileriniz tuğlalanabilir. Ya da daha kötüsü - kodunuz bir sitedeki diğer işlevleri bozar.


2

Event.preventDefault- tarayıcı varsayılan davranışını durdurur. Şimdi tarayıcı varsayılan davranışı nedir. Bir tutturma etiketiniz olduğunu ve href özelliğine sahip olduğunu ve bu tutturma etiketinin bir tıklama etkinliğine sahip bir div etiketinin içine yerleştirildiğini varsayalım. Tutturma etiketinin varsayılan davranışı tutturulması gereken tutturma etiketine tıklandığındadır, ancak bu durumda event.preventDefault öğesinin yaptığı şey, gezinmeyi durdurmasıdır. Ancak hiçbir zaman olayın köpürmesini veya olayın yükselmesini durdurmaz.

<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');
});

Sonuç

"öğe tıklandı"

"kapsayıcı tıklandı"

Şimdi event.StopPropation, olayın köpürmesini veya olayın yükselmesini durdurur. Şimdi yukarıdaki örnekle

$('.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');
});

Sonuç olacak

"öğe tıklandı"

Daha fazla bilgi için bu bağlantıya bakın https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/


1

event.preventDefault(); Bir öğenin varsayılan eyleminin gerçekleşmesini durdurur.

event.stopPropagation(); Etkinliğin DOM ağacını köpürmesini önleyerek üst işleyicilerin olay hakkında bilgilendirilmesini önler.

Örneğin, a'nın içine eklenmiş bir tıklama yöntemine sahip bir bağlantı varsa DIVveya FORMayrıca bir tıklama yöntemi eklenmişse, DIVveya FORMtıklama yönteminin tetiklenmesini önler .


-3

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.