javascript - event.stopPropagation ve event.preventDefault arasındaki fark nedir?
Görünüşe göre aynı şeyi yapıyorlar...
Biri modern, diğeri eski mi? Yoksa farklı tarayıcılar mı destekliyor?
Olayları kendim (çerçeve kullanmadan) yönettiğimde, her zaman her ikisini de kontrol ederim ve mevcutsa her ikisini de çalıştırırım. (Ayrıca return false yapıyorum, ama bunun node.addEventListener ile eklenen olaylarda çalışmadığını hissediyorum).
Peki neden ikisi de? İkisini de kontrol etmeye devam mı etmeliyim? Yoksa gerçekten bir fark var mı?
(Biliyorum, çok soru, ama hepsi bir şekilde aynı =))
Cevap #1
stopPropagation, geçerli olayın yakalama ve kabarcıklanma aşamalarında daha fazla yayılmasını engeller.
preventDefault, tarayıcının o olay üzerinde 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>stopPropagation ile sadece button'ın tıklama işleyicisi çağrılır, div'in tıklama işleyicisi hiçbir zaman çalışmaz.
Oysa ki preventDefault kullanırsanız, yalnızca tarayıcının varsayılan eylemi durdurulur, ancak div'in tıklama işleyicisi yine de çalışır.
Aşağıda MDN'den DOM olay özellikleri ve yöntemleri ile ilgili bazı belgeler bulunmaktadır:
event.cancelBubbleevent.preventDefault()event.returnValueevent.stopPropagation()
IE9 ve FF için sadece preventDefault ve stopPropagation kullanabilirsiniz.
IE8 ve altını desteklemek için stopPropagation yerine cancelBubble kullanın ve preventDefault yerine returnValue kullanın
Cevap #2
Terminoloji
quirksmode.org'dan:
Olay yakalama
Olay yakalama kullandığınızda
| | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | -----------------------------------element1'in olay işleyicisi ilk olarak tetiklenir, element2'nin olay işleyicisi en son tetiklenir.
Olayın kabarcıklanması
Olay kabarmasını kullandığınızda
/ \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | -----------------------------------element2'nin olay işleyicisi ilk olarak tetiklenir, element1'in olay işleyicisi en son tetiklenir.
W3C olay modelinde gerçekleşen herhangi bir olay, hedef elemana ulaşana kadar önce yakalanır ve ardından tekrar yukarı doğru yayılır.
| | / \ -----------------| |--| |----------------- | element1 | | | | | | -------------| |--| |----------- | | |element2 \ / | | | | | -------------------------------- | | W3C event model | ------------------------------------------
Arayüz
w3.org'dan, olay yakalama için:
Eğer yakalayan
EventListener, olayın daha fazla işlenmesini engellemek istiyorsa,EventarayüzününstopPropagationmetodunu çağırabilir. Bu, olayın daha fazla dağıtılmasını engeller, ancak aynı hiyerarşi seviyesinde kayıtlı ekEventListenerlar hala olayı alır. Bir olayınstopPropagationmetodu çağrıldıktan sonra, bu metoda yapılacak ek çağrılar herhangi bir ek etki yaratmaz. Eğer ek yakalayıcılar yoksa vestopPropagationçağrılmamışsa, olay hedefin üzerindeki uygunEventListenerları tetikler.
Olay kabarması için:
Herhangi bir olay işleyicisi,
EventarayüzününstopPropagationyöntemini çağırarak olayın daha fazla yayılmasını engellemeyi seçebilir. Eğer herhangi birEventListenerbu yöntemi çağırırsa, mevcutEventTargetüzerindeki tüm ekEventListener’lar tetiklenecek, ancak baloncuk oluşumu o seviyede duracaktır. Daha fazla baloncuk oluşmasını engellemek için yalnızca bir kezstopPropagationçağrılması yeterlidir.
Etkinlik iptali için:
İptal,
Event'inpreventDefaultyöntemini çağırarak gerçekleştirilir. Bir veya daha fazlaEventListener, olay akışının herhangi bir aşamasındapreventDefaultçağırırsa, varsayılan eylem iptal edilecektir.
Örnekler
Aşağıdaki örneklerde, web tarayıcısındaki bir köprüye tıklamak olayın akışını tetikler (olay dinleyicileri çalıştırılır) ve olay hedefinin varsayılan eylemini (yeni bir sekme açılır) gerçekleştirir.
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: bu, çıktıyla sonuçlanır
DIV event capture
A event capture
A event bubbling
DIV event bubbling
Örnek 2: Fonksiyona stopPropagation() eklemek
function capturingOnClick1(ev) {
el.innerHTML += "DIV event capture<br>";
ev.stopPropagation();
}
çıktıda sonuçlar
DIV event capture
Olay dinleyicisi, olayın aşağı ve yukarı doğru yayılmasını engelledi. Ancak varsayılan eylemi (yeni bir sekme açılmasını) engellemedi.
Örnek 3: Fonksiyona stopPropagation() eklemek
function capturingOnClick2(ev) {
el.innerHTML += "A event capture<br>";
ev.stopPropagation();
}
veya fonksiyon
function bubblingOnClick2(ev) {
el.innerHTML += "A event bubbling<br>";
ev.stopPropagation();
}
çıktıda sonuçlar
DIV event capture
A event capture
A event bubbling
Bunun nedeni her iki olay dinleyicisinin de aynı olay hedefine kaydedilmiş olmasıdır. Olay dinleyicileri olayın yukarı doğru daha fazla yayılmasını engelledi. Ancak varsayılan eylemi (yeni bir sekmenin açılması) engellemediler.
Örnek 4: herhangi bir fonksiyona, örneğin preventDefault() eklemek
function capturingOnClick1(ev) {
el.innerHTML += "DIV event capture<br>";
ev.preventDefault();
}
yeni bir sekmenin açılmasını engeller.
Cevap #3
false dön;
return false; çağırdığınızda 3 farklı şey yapar:
event.preventDefault()- Tarayıcının varsayılan davranışını durdurur.event.stopPropagation()- Olayın DOM üzerinde yayılmasını (veya 'yukarı doğru kabarmasını') engeller.- Çağrıldığında geri arama yürütmesini durdurur ve hemen geri döner.
Bu davranışın normal (jQuery dışı) olay işleyicilerinden farklı olduğunu unutmayın; özellikle return false'un olayın yukarı doğru yayılmasını durdurmadığını.
preventDefault();
preventDefault(); bir şeyi yapar: Tarayıcının varsayılan davranışını durdurur.
Ne zaman kullanmalısınız?
Onların ne yaptığını biliyoruz ama ne zaman kullanılacağını? Basitçe söylemek gerekirse, ne başarmak istediğinize bağlıdır. Varsayılan tarayıcı davranışını “sadece” engellemek istiyorsanız preventDefault(); kullanın. Varsayılan tarayıcı davranışını engellemek ve olayın DOM içinde yayılmasını önlemek istiyorsanız return false; kullanın. return false; kullanacağınız çoğu durumda aslında istediğiniz şey preventDefault().
Ö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ırsanız, hiperlinki ‘Click here to visit stackoverflow.com‘ göreceksiniz. Şimdi o linke tıkladığınızda önce javascript uyarısı Link Clicked görünecek. Sonra javascript uyarısı div Clicked gözükecek ve hemen ardından stackoverflow.com sitesine yönlendirileceksiniz.
Ö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ırsanız, ‘Click here to visit stackoverflow.com‘ bağlantısını göreceksiniz. Şimdi o bağlantıya tıkladığınızda önce Link Clicked JavaScript uyarısını alırsınız. Sonra div Clicked JavaScript uyarısını alırsınız. Daha sonra ‘Click here to visit stackoverflow.com‘ bağlantısı ‘Click event prevented‘ metni ile değiştirilir ve stackoverflow.com sitesine yönlendirilmezsiniz. Bu, varsayılan tıklama işleminin tetiklenmesini önlemek için kullandığımız event.preventDefault() metodundan kaynaklanmaktadır.
Ö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 sefer eğer Link'e tıklarsanız, executeParent() fonksiyonu çağrılmayacak ve bu sefer javascript uyarısı div Clicked almayacaksınız. Bunun nedeni, event.stopPropagation() yöntemi kullanarak olayı üst div'e iletmesini engellemiş olmamızdır. Sonraki adımda, ‘Click here to visit stackoverflow.com‘ olan hiperlinkin ‘Click event is going to be executed‘ metni ile değiştirildiğini göreceksiniz ve hemen stackoverflow.com'a yönlendirileceksiniz. Bunun nedeni, bu sefer event.preventDefault() yöntemi kullanarak varsayılan tıklama eyleminin tetiklenmesini engellememiş olmamızdır.
Ö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>Eğer Bağlantıya tıklarsanız, executeParent() fonksiyonu çağrılmayacak ve javascript uyarısını almayacaksınız. Bu, olayın üst div'e yayılmasını event.stopPropagation() yöntemiyle engellediğimizden kaynaklanmaktadır. Sonraki adımda, ‘stackoverflow.com'u ziyaret etmek için buraya tıklayın’ bağlantısının, ‘Tıklama olayı engellendi’ metni ile değiştirildiğini göreceksiniz ve stackoverflow.com'a yönlendirilmeyeceksiniz. Bunun nedeni, bu sefer varsayılan tıklama eyleminin event.preventDefault() yöntemiyle tetiklenmesini engellemiş olmamızdır.
Örnek 5:
return false için üç örneğim var ve hepsi tam olarak aynı şeyi yapıyor gibi görünüyor (sadece false döndürüyor), ancak gerçekte sonuçlar oldukça farklı. İşte yukarıdakilerde aslında ne olduğu.
vakalar :
- Satır içi bir olay işleyicisinden false döndürmek, tarayıcının bağlantı adresine gitmesini engeller, ancak olayın DOM üzerinden yayılmasını durdurmaz.
- Bir jQuery olay işleyicisinden false döndürmek, tarayıcının bağlantı adresine gitmesini önler ve olayın DOM üzerinden yayılmasını durdurur.
- Normal bir DOM olay işleyicisinden false döndürmek hiçbir şey yapmaz.
Üç örneği de göreceğiz.
- Satır içi false döndür.
<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>- Bir jQuery olay işleyicisinden false döndürmek.
<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>- Normal bir DOM olay işleyicisinden false döndürmek.
<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. Bu örneklerin nasıl çalıştığını görmek için hepsini bir HTML dosyasında çalıştırmayı deneyin.
Cevap #4
Bu buradan alınan alıntıdır
Event.preventDefault
preventDefault yöntemi, bir olayın varsayılan işlevini yerine getirmesini engeller. Örneğin, bir A öğesinde preventDefault kullanarak, o öğeye tıklamanın mevcut sayfadan ayrılmasını durdurabilirsiniz:
//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 devre dışı bırakılmış olsa da, olay DOM boyunca yukarı doğru yayılmaya devam eder.
Event.stopPropagation
İkinci yöntem olan stopPropagation, olayın varsayılan işlevinin gerçekleşmesine izin verir ancak olayın yayılmasını engeller:
//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, bir çocuğundaki belirli bir olay hakkında üst öğelerin bilgi sahibi olmasını etkili bir şekilde durdurur.
Basit bir durdurma yöntemi olayları hızlı bir şekilde yönetmemize izin verirken, kümeleşme ile tam olarak ne olmasını istediğinizi düşünmek önemlidir. Bahse girerim ki bir geliştirici aslında zamanın %90'ında sadece preventDefault yapmak ister! Olayı yanlış şekilde "durdurmak", ileride size birçok sorun çıkarabilir; eklentileriniz çalışmayabilir ve üçüncü taraf eklentiler bozulabilir. Daha da kötüsü -- kodunuz bir sitedeki diğer işlevleri bozabilir.
Cevap #5
event.preventDefault()
Tarayıcının varsayılan davranışını (örneğin bir bağlantıyı açmayı) engeller, ancak olayın DOM üzerinde yukarı doğru yayılmasını durdurmaz.event.stopPropagation()
Olayın DOM içinde yukarı doğru yayılmasını engeller, ancak tarayıcının varsayılan davranışını durdurmaz.return false;
Genellikle jQuery kodunda görülen bu ifade, tarayıcının varsayılan davranışını engeller, olayın DOM üzerinde yukarı doğru yayılmasını önler ve herhangi bir geri çağırmadan hemen değer döndürür.
Yukarıdaki parçanın alındığı yerden örneklerle birlikte bu gerçekten güzel ve kolay 4 dakikalık okumaya göz atın.
