在平時項目中,如果遇到需要阻止瀏覽器默認行為,大家經常會用return false;和event.preventDefault()來阻止,但對它倆的區別還是有些一知半解,於是看了文檔,查了些資料,在此總結下它倆的區別,順便帶上event.stopPropagation()一起區分下。
一、原生js中:
關於return false和preventDefault:
在W3C Document Object Model Events Specification1.3版本中提到過:
The EventListener interface is the primary method for handling events. Users implement the EventListener interface
and register their listener on an EventTarget using the AddEventListener method. The users should also remove their
EventListener from its EventTarget after they have completed using the listener.
handleEvent
This method is called whenever an event occurs of the type for which the EventListener interface was registered.
同時,在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.
也就是說,事件處理程序的返回值只對通過屬性注冊的處理程序才有意義,如果我們未通過addEventListener()函數來綁定事件的話,若要禁止默認事件,用的就是return false; 但如果要用addEventListener()或者attachEvent()來綁定,就要用preventDefault()方法或者設置事件對象的returnValue屬性。
而H5規范中為什么要OtherWise來強調return false,因為規范中有指出在mouseover等幾種特殊事件情況下,return false;並不一定能終止事件。所以,在實際使用中,我們需要盡量避免通過return false;的方式來取消事件的默認行為。
二、在jQuery中:
這里需要先了解下事件傳遞機制:
例如鼠標被按下后,mousedown事件被觸發。
事件先從document->ancestor element->...->parent->event.target(在此元素上按下的鼠標)->parent->...->ancestor element->document.
事件走了一個循環,從documet到event.target再回到document,從event.target到document的過程叫做冒泡。
event.stopPropagation(); // 事件停止冒泡到,即不讓事件再向上傳遞到document,但是此事件的默認行為仍然被執行,如點擊一個鏈接,調用了event.stopPropagation(),鏈接仍然會被打開。
event.preventDefault(); // 取消了事件的默認行為,如點擊一個鏈接,鏈接不會被打開,但是此事件仍然會傳遞給更上一層的先輩元素。
在事件處理函數中使用 return false; 相當於同時調用了event.stopPropagation()和event.preventDefault(),事件的默認行為不會被執行,事件也不會冒泡向上傳遞。
此時在jQuery中,return false;就不是簡單的覆蓋面和規范的問題了。在jQuery事件處理函數中調用return false;相當於同時調用了preventDefault和stopPropagation方法,這會導致當前元素的事件無法向上冒泡,在事件代理模式下,會導致問題。
比如,我有一個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;和event.preventDefault()二者的區別。
即盡量不要用return false;來阻止event的默認行為。
附:
event.preventDefault()方法並不被ie支持,在ie下需要用window.event.returnValue = false; 來實現。一般都是這樣寫,代碼如下:
function stopDefault( e ) {
if ( e && e.preventDefault ){
e.preventDefault(); //支持DOM標准的瀏覽器
} else {
window.event.returnValue = false; //IE
}
}
也可以處理ie || firefox下圖片拖動的問題。
document.onmousemove=function(ev){ var oEvent=ev||event; if(oEvent.preventDefault){oEvent.preventDefault();} else{oEvent.returnValue=false;} }