白話解釋 Javascript事件preventDefault,stopPropagation及return false的區別

來源: 我的博客

想必好多童鞋都有直接複製粘貼event.preventDefault() 或者event.stopPropagation() 的經歷,可是爲何這樣作不甚瞭解,今天咱們的目的就是要完全搞懂這一區別。javascript

javascript中的「事件傳播」模式

爲了完全弄清楚它們之間的區別,我不得不要先說一下javascript中兩種事件傳播模式:html

- 捕獲模式(capturing)
- 冒泡模式(bubbling)

捕獲模式又稱爲「滴流模式」(trickling),我的認爲滴流模式更好理解,滴流就是「從上向下」,而冒泡就是「從下向上」,好了,先記住這兩種模式的特色。java

同時你還要記住,這兩種模式是爲了幹什麼的?
這兩種模式就是爲了一點:決定html中「元素」(好比div, p, button)接收到事件的「順序」!固然接收到事件的順序不一樣,天然事件監聽函數被觸發的順序就不一樣了,因而間接地就出現了監聽函數被執行順序的不一樣。git

因此。。github

捕獲模式

當事件發生時,該事件首先被最外層元素接受到,而後依次向內層元素傳播。(從上向下)瀏覽器

冒泡模式

當事件發生時,該事件首先被最內層元素接受到,而後依次向外層元素傳播。(從下向上)函數

順便提一句,之前網景公司主推捕獲模式而微軟則偏向於冒泡模式,不過二者都是W3C DOM事件標準(2000)。spa

IE9如下僅僅支持冒泡模式,可是IE9+以及如今的主流瀏覽器都支持兩種模式了。code

聲明方式

用哪一種事件傳播方式徹底是咱們本身說了算的,咱們可使用htm

addEventListener(type, listener, useCapture)

來註冊事件處理方式,以及以何種傳播模式進行。

例子

<div id="outerMost">
    <div id="middle">
        <a href="" id="innerMost" >click</a>
    </div>
</div>

咱們能夠對上述代碼添加一些樣式,這樣在網頁中更直觀。

<div id="outerMost" style="border: 1px solid black; width: 150px; height: 120px; padding: 20px;">
    outerMost
    <div id="middle" style="border: 1px solid black; width: 60px; height: 60px; padding: 20px;">
        Middle
        <a href="" id="innerMost" style="border: 1px solid black; width: 30px; height: 20px; display: block; margin: 20px;">click</a>
    </div>
</div>

如圖:圖片描述

使用事件捕獲模式註冊事件監聽

對最外層,中間層,最內層分別用「捕獲」模式註冊事件監聽,咱們上面說了,若是使用捕獲模式,那麼addEventListener第三個參數應該是true,不然則是冒泡模式,若是不聲明,默認爲冒泡模式。

var outerElement = document.getElementById('outerMost');
var middleElement = document.getElementById('middle');
var innerElement = document.getElementById('innerMost');

outerElement.addEventListener('click', function () {
    console.log('trigger outermost div');
}, true);
middleElement.addEventListener('click', function () {
    console.log('trigger middle div');
}, true);
innerElement.addEventListener('click', function () {
    console.log('trigger innermost button');
}, true);

咱們點擊中間層Middle字樣,如圖:
圖片描述

能夠看到,事件觸發從外向裏進行,若是你們把addEventListener中第三個參數改成false或者留空,點擊middle字樣,則會獲得相反的結果,你們能夠本身試一下。

preventDefault 及 stopPropagation函數區別

終於到了談一談preventDefault 和 stopPropagation了,你們可能注意到了,我上面的例子中沒有涉及到點擊click連接,爲何呢?你們能夠試一下,點擊click會發生什麼?它會又當即跳轉到了當前頁面(由於咱們href是一個空鏈接,這是連接元素的一個默認特性),雖然咱們的監聽函數被執行了,可是有時候咱們不想這個默認特性被執行,好比,咱們可能想在監聽函數裏面改變div的背景顏色等等,這樣若是這個連接元素a默認特性的存在就會當即「刷新」了該頁面,讓咱們的改變背景顏色沒法進行。

因此爲了「阻止」元素的「默認特性」,因此事件對象中有了一個preventDefault方法,以下:

innerElement.addEventListener('click', function (event) {
    event.preventDefault();
    console.log('trigger innermost button');
}, true);

這樣咱們點擊click就會獲得:

trigger outermost div
trigger middle div
trigger innermost button

那麼stopPropagation呢?
向上面這種狀況,若是當你點擊click的時候,只想出發綁定在click上的監聽函數,而不想觸發「傳播鏈」上的其餘函數,那麼則使用stopPropagation。

注意:你在那個事件監聽函數中使用event.stopPropagation();那麼傳播鏈就會終止,向上面這個例子,由於咱們使用的是捕獲模式,即便咱們添加了:

innerElement.addEventListener('click', function (event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('trigger innermost button');
}, true);

依然會獲得和上面同樣的結果,爲何呢?由於捕獲模式是由外往裏傳播,咱們只是在a這裏阻止了繼續像裏傳播,由於沒有更裏的元素了,因此結果同樣,爲了更好地演示,咱們能夠把捕獲模式改成冒泡模式以下:

var outerElement = document.getElementById('outerMost');
var middleElement = document.getElementById('middle');
var innerElement = document.getElementById('innerMost');

outerElement.addEventListener('click', function (event) {
    console.log('trigger outermost div');
});
middleElement.addEventListener('click', function () {
    console.log('trigger middle div');
});
innerElement.addEventListener('click', function (event) {
    event.preventDefault();
    event.stopPropagation();
    console.log('trigger innermost button');
});

這樣點擊click,就只獲得了一條log:

trigger innermost button

return false;

最後說一下return false; 這是jQuery中提供,好比:

$('#innermost').on('click', function () {
    return false;
})

它幫咱們同時作了:

- event.preventDefault();
    - event.stopPropagation();

這兩個工做,你能夠看作是一種快捷方式,可是你在原生javascript中的監聽回調函數中寫return false; 是沒有任何用的。好比:

innerElement.addEventListener('click', function (event) {
    return false;
});

只是jQuery提供的一種特性。

來源:我的博客

相關文章
相關標籤/搜索