preventDefault,stopPropagation,return false三者的區別

以樂之名發表於2017-08-31

逛帖子的時候看到道友發的前端面試題,

preventDefault(), stopPropagation(), return false三者的區別

這三者的使用想必大家並不陌生,但是細想之下還是有可究之處。

preventDefault()

阻止元素在瀏覽器中的預設行為

<a id="link" href="http://wuliv.com">網站</a>
$(`#link`).click(function(event){
    event.preventDefault(); // 阻止了a連結href的訪問或跳轉
})

stopPropagation()

事件冒泡:當一個元素上的事件被觸發時,比如滑鼠點選了一個按鈕,同樣的事件將會在該按鈕元素的所有父級/祖先元素上觸發。這一個過程就被稱為事件冒泡。它是由子級元素先觸發,父級元素後觸發,由內而外(由下往上)的一個流程。與之順序相反的是事件捕獲。

事件捕獲:父級元素先觸發,子級元素後觸發,在此僅做了解。

<body>
  <div id="inner">
    <p>事件冒泡例子</p>
    <button id="btn">我要彈個框</button>
  </div>
</div>

$(`#btn`).click(function(event){
  event.stopPropagation(); // 阻止了事件冒泡,不會觸發"#inner, body"的點選事件  
  console.log(`#btn`)
})

$(`#inner`).click(function(event){
    // #btn 阻止了冒泡,這裡不會執行
    // 如果不使用stopPropagation, 當#btn點選時,這裡也會執行
    console.log(`#inner`)
})

$(`body`).click(function(event){
    // #btn 阻止了冒泡,.btn點選不會影響到我
    // 如果不使用stopPropagation, 當#btn點選時,這裡也會執行
    console.log(`body`)
})

// 使用了stopPropagation()輸出
`#btn`

// 不使用stopPropagation()輸出
`#btn`
`#inner`
`body`

stopImmediatePropagation()

阻止物件繫結的剩餘的事件處理函式方法的執行,並阻止當前事件的冒泡。
可以理解為stopImmediatePropagation是stopPropagation的升級版,除了阻止冒泡,還能阻止結束掉當前物件未執行的其它繫結事件方法。

jQuery中一個物件可以繫結多個事件方法,執行順序會按照繫結的先後順序來執行

<body>
    <div id="inner">
        <p>stopImmediatePropagation()例子</p>
        <button id="btn">按鈕</btn>
    </div>
</body>

$(`body`).click(function(event){
    // body 點選
    console.log(`body`);
});

$(`#inner`).click(function(event){
    // #inner 點選
    console.log(`#inner`);
})

$(`#btn`).click(function(event){
    // 第一個#btn點選
    e.stopImmediatePropagation();
    console.log(`#btn 1`);
})

$(`#btn`).click(function(event){
    // 第二個#btn點選
    console.log(`#btn 2`)
})

// 最終輸出
`#btn 1` // (因為stopImmediatePropagation阻止了#btn繫結的剩餘未執行的事件方法,並且阻止了冒泡)

// 如果不使用stopImmediatePropagation, 將輸出
`#btn 1`
`#btn 2`
`#inner`
`body`
同個物件執行順序按繫結順序執行,冒泡則由內向外執行

return false

“return false” 相信不少同學會用來阻止元素在瀏覽器中的預設行為,
拿它當preventDefault()使用,但其實“return false”做的事情不僅僅只是阻止預設行為

當呼叫“return false”時,它執行了以下三件事情

  1. event.preventDefault()

  2. event.stopPropagation()

  3. 停止回撥函式執行並立即返回

1,2點還好理解,那麼第3點是怎麼回事?
return語句會終止函式的執行並返回函式的值。所以不管是否返回false或是其它值,return語句後面的程式碼都不會執行。而返回false,使它具備了preventDefault和stropPropagation的功能

$(`a`).click(function(){
    return false; // return false直接返回了,並不會執行alert
    alert(`我沒有被彈出來`);
})

// preventDefault 和 stopPropagation 並不會阻止回撥函式的執行

總結

很多jQuery教程在程式碼演示中用“return false”來阻止執行瀏覽器的預設行為。
久而久之,很多同學習慣濫用“return false”來代替preventDefault

大多數情況下,我們僅僅是想要它執行跟preventDefault的功能而已,但它卻自作主張地幫你執行了另外兩步操作。
比較好的程式設計習慣是,需要用到該事件方法再去呼叫,否則應該避免冗餘事件的執行。
就像prevnetDefault完成它該有的工作,並不會阻止父節點繼續處理事件,使得程式碼更加靈活,更易於維護。

日常開發中還是要慎用“return false”,除非你同時需要preventDefault和stopPropagation,並且確定你的回撥函式執行完成後呼叫,那麼你可以使用“return false”,否則還是用preventDefault 或 stopPropagation 更好些。

作者:以樂之名
本文原創,有不當的地方歡迎指出。轉載請指明出處。

參考文章:《preventDefault()、stopPropagation()、return false 之間的區別》

相關文章