不要用return false阻止event的預設行為

weixin_33850890發表於2015-08-23

當我們點選一個a標籤時,如果這個標籤的href指向了另一個地址,那麼瀏覽器會預設跳轉到此地址。在頁面中,有時我們需要觸發點選事件,但是又不想觸發預設行為,就需要阻止event的預設行為了。

常規做法

眾所周知,IE早期版本的event物件與DOM標準中的event物件並不相同,所以一般的相容性寫法是這樣的:

if (event.preventDefault) {
    event.preventDefault(); //支援DOM標準的瀏覽器
} else {
    event.returnValue = false; //IE
}

非常規

在原生JS下

但是還有一種人,喜歡在函式結尾用return false;來阻止event預設行為,不過這種方法覆蓋面不全,不建議使用,先來看規範是如何定義的:
W3C Document Object Model Events Specification 1.3.1版中。事件註冊介面 提及到:

handleEvent
This method is called whenever an event occurs of the type for which the EventListener interface was registered. [...] No Return Value

1.2.4. Event Cancelation 文件中也提到:

Cancelation is accomplished by calling the Event's preventDefault method. If one or more EventListeners call preventDefault during any phase of event flow the default action will be canceled.

HTML5 Section 6.1.5.1 of the HTML Spec規範定義如下:

Otherwise
If return value is a WebIDL boolean false value, then cancel the event.

為什麼要OtherWise,因為規範中有指出在mouseover等幾種特殊事件情況下,return false;並不一定能終止事件。

所以,在實際使用中,請儘量避免通過return false;的方式來取消事件的預設行為。

在jQuery下:

jQuery中,就不是簡單的覆蓋面和規範的問題了。在jQuery事件處理函式中呼叫return false;相當於同時呼叫了preventDefaultstopPropagation方法,這會導致當前元素的事件無法向上冒泡,在事件代理模式下,會導致問題。

比如,我有一個div容器,裡面是 幾個a標籤,它們的href裡分別儲存了url地址,這個url被用來動態的載入到下面的div#content中,這裡為了簡單演示,就只把url字串寫入到div#content中:

<div id="container">
   <a href="/content1.html">content1</a>
   <a href="/content2.html">content2</a>  
   <div id="content">我會根據點選連結的url不同而改變的</div>
</div>
// 為container下的所有a標籤繫結click事件處理函式
$("#container").click(function (e) {
   if (e.target.nodeName == "A") {
        $("#content").html(e.target.href);
    }
});
// 再為a標籤繫結click事件處理函式,阻止預設事件
$("#container a").click(function () {
  return false;
});

上面的程式碼執行後,雖然阻止了a標籤的點選預設行為,但同時停止了冒泡事件,導致其外層的父元素無法檢測到click事件,所以jQuery中請明白return false;preventDefault二者的區別。

總結

不要用return false;來阻止event的預設行為

相關文章