javascript - prevent - stoppropagation用法




event.stopPropagation和event.preventDefault之間有什麼區別? (4)

他們似乎也在做同樣的事情......是現代人還是老人? 或者他們是否支持不同的瀏覽器?

當我自己處理事件(沒有框架)時,我總是檢查兩者,並在兩者都存在的情況下執行。 (我也return false ,但我感覺不能用node.addEventListener附帶的事件)。

那為什麼呢? 我應該繼續檢查嗎? 或者實際上有區別?

(我知道,很多問題,但它們都是相同的=))


event.preventDefault(); 停止發生元素的默認操作。

event.stopPropagation(); 防止事件冒泡DOM樹,阻止任何父處理程序被通知事件。

例如,如果在附有點擊方法的DIVFORM內附加了click方法的鏈接,則會阻止DIVFORM點擊方法觸發。


stopPropagation停止事件冒泡事件鏈。

preventDefault可防止瀏覽器在該事件中執行的默認操作。

假設你有

<div id="foo">
 <button id="but" />
</div>

$("#foo").click(function() {
   // mouse click on div
});

$("#but").click(function(ev) {
   // mouse click on button
   ev.stopPropagation();
});

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

$("#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只會調用按鈕單擊處理程序 ,並且divs單擊處理程序不會觸發。

如果你只是preventDefault ,默認只有瀏覽器的默認行為被停止,但div的點擊處理程序仍然會觸發。

以下是關於來自MDNMSDN的DOM事件對象的一些文檔

MDN:

對於IE9和FF,你可以使用preventDefault&stopPropagation。

為了支持IE8並使用cancelBubble替換stopPropagation ,並用returnValue替換preventDefault


來自quirksmode.org

事件捕獲

當你使用事件捕獲

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

element1的事件處理程序首先觸發,element2的事件處理程序最後觸發。

事件冒泡

當你使用事件冒泡
               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

element2的事件處理程序首先觸發,element1的事件處理程序最後觸發。

首先捕獲在W3C事件模型中發生的任何事件,直到它到達目標元素,然後再次冒泡

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

https://www.w3.org/TR/DOM-Level-2-Events/events.html

如果捕獲的EventListener希望阻止進一步處理事件發生,它可能會調用Event接口的stopPropagation方法。 這將阻止事件的進一步分派,儘管在同一層級上註冊的附加EventListener仍將接收事件。 一旦調用了事件的stopPropagation方法,對該方法的進一步調用就沒有其他效果。 如果不存在其他捕獲器並且尚未調用stopPropagation,則該事件會在目標本身上觸發相應的EventListener。

對於冒泡:

任何事件處理程序可以選擇通過調用Event接口的stopPropagation方法來阻止進一步的事件傳播。 如果任何EventListener調用此方法,則將觸發當前EventTarget上的所有其他EventListener,但冒泡將在該級別停止。 只有一個呼叫停止傳播是必需的,以防止進一步冒泡。

例子

HTML

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

JavaScript的

var el = document.getElementById("c");
function captureOnClickA(e){
    el.innerHTML += "DIV event capture<br>";
}
function captureOnClickB(e){
    el.innerHTML += "A event capture<br>";
}
function bubblingOnClickA(e){
    el.innerHTML += "DIV event bubbling<br>";
}
function bubblingOnClickB(e){
    el.innerHTML += "A event bubbling<br>";
}
document.getElementById("a").addEventListener("click",captureOnClickA, true);
document.getElementById("b").addEventListener("click",captureOnClickB, true);
document.getElementById("a").addEventListener("click",bubblingOnClickA, false);
document.getElementById("b").addEventListener("click",bubblingOnClickB, false);

Demo ,在這個例子中,執行四個事件監聽器,並在瀏覽器中打開一個新的選項卡。 輸出是:

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

將第一個功能更改為:

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

將導致這個輸出:

DIV event capture

這意味著事件的向下傳播停止並且其向上傳播。 Demo 。 但它不會阻止標籤打開。

stopPropagation()添加到

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

Demo

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

Demo ,將導致相同的輸出,因為它們在當前的EventTarget上:

DIV event capture
A event capture
A event bubbling

在這兩種情況下,該事件阻止了向母公司冒泡。 這兩個也不會阻止標籤打開。 為了防止打開標籤,我們需要使用preventDefault()來防止默認的瀏覽器操作:

function captureOnClickA(e){
    el.innerHTML += "DIV event capture<br>";
    e.stopPropagation();
    e.preventDefault();
}

現在該選項卡將不會打開,並且只有一個事件偵聽器將被執行。 Demo


這是從here引用

Event.preventDefault

preventDefault方法可防止事件執行其默認功能。 例如,您可以使用A元素上的preventDefault來停止單擊離開當前頁面的元素:

//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%的時間! 錯誤地“停止”一個事件可能會導致你無數的麻煩; 你的插件可能無法正常工作,你的第三方插件可能會被堵塞。 或者更糟糕的是 - 您的代碼會破壞網站上的其他功能。







stoppropagation