前段時間開發中,遇到一個父元素和子元素都有事件時,發現會出現事件冒泡現象,雖然知道ev.stopPropagation()和ev.stopPropagation()其中一個是阻止事件冒泡,卻不知ev.preventDefault()和ev.stopPropagation()以及return fals ...
前段時間開發中,遇到一個父元素和子元素都有事件時,發現會出現事件冒泡現象,雖然知道ev.stopPropagation()和ev.preventDefault()其中一個是阻止事件冒泡,卻不知ev.preventDefault()和ev.stopPropagation()以及return false之間的區別,於是閑了就學了一下。
在此之前,先複習一下事件機制。
dom事件通常會有三種情況:
捕獲階段:從外向里依次查找元素。
目標階段:從當前事件源本身的操作
冒泡階段:從內到外依次觸發相關的行為。
如下圖可以得知標準事件觸發情況(借Lazymr博主的圖一用):
從圖中可知,有些情況我們不讓父元素觸發子元素所帶來的事件。所以ev.preventDefault()和ev.stopPropagation()以及return false就出來了。
ev.preventDefault():
這個是阻止預設行為觸發,什麼是預設行為,即標簽屬性本身具備的功能。就是類似與a標簽所帶的href和submit所帶的提交等等。
對於預設行為,瀏覽器優先實行事件函數後實行預設行為。
<body> <a href="http://www.baidu.com" onclick="btn()">點擊</a> <script type="text/javascript"> document.querySelector('a').onclick = function (ev) { alert('警告!'); ev.preventDefault(); } </script> </body>
出現的結果是:只彈出警告的彈窗,之後沒有跳轉到百度頁面。
相容性處理
function stopDefault( e ) { if ( e && e.preventDefault ){ e.preventDefault(); //支持DOM標準的瀏覽器 } else { window.event.returnValue = false; //IE } }
ev.stopPropagation()
阻止事件冒泡。什麼是事件冒泡;上一個圖片已經解釋清楚了。事件可以在各層級的節點中傳遞,不管是冒泡還是捕獲,有時我們希望事件在特定節點執行完之後不再傳遞,可以使用事件對象的 ev.stopPropagation() 方法。
<body> <br /> <div id="parent" onclick="console.log(this.id)"> <p>parent</p> <div id="child" onclick="doSomething(this,event);"> <p>child</p> </div> </div> <script type="text/javascript"> function doSomething(obj, ev){ console.log(obj.id) } </script> </body>
點擊child的結果會觸發事件冒泡。結果如下:
如果要實現只出現child,那麼就要用到ev.stopPropagation() 了。
<body> <br /> <div id="parent" onclick="console.log(this.id)"> <p>parent</p> <div id="child" onclick="doSomething(this,event);"> <p>child</p> </div> </div> <script type="text/javascript"> function doSomething(obj, ev){ console.log(obj.id); ev.stopPropagation(); } </script> </body>
結果如下:點擊child只出現child。
這個有相容性, IE8 及以前版本都不支持,IE 的事件對象包含特有的屬性 cancelBubble
,只要將它賦值為 true 即可阻止事件繼續。ie下可以用這個ev.cancelBubble=true。
可以封裝成一個函數:
function stopBubble(ev) { var ev=ev||window.event if(window.event) { ev.cancelBubble=true; //ie阻止冒泡 }else { ev.stopPropagation(); //其他瀏覽器組織冒泡 } }
return false
包含特有退出執行 return false
之後的所有觸發事件和動作都不會被執行,有時候 return false
可以用來替代 stopPropagation()
和 preventDefault()來阻止預設行為發生和冒泡。
<body> <br /> <div> <a href="http://www.baidu.com">點擊</a> </div> <script type="text/javascript"> document.querySelector('a').onclick=function(){ alert('警告'); return false; } </script> </body>
結果是 只出現警告的彈窗,但沒有跳轉到百度頁面。
如果將return false放到alert('警告')前面 。結果會是什麼都不顯示,原因是return false提到了終止事件和預設行為。
return false和ev.stopPropagation()的區別是:
return false不僅阻止了冒泡而且還阻止了事件本身。
ev.stopPropagation()只阻止了冒泡。
註意:雖然return false能夠替代前兩個阻止預設行為和冒泡,但是也有其他作用,比如終止迴圈等等,所以會有意想不到的結果,因此能用ev.preventDefalut()來阻止預設行為和ev.stopPropagation()阻止冒泡最好,提高代碼的高效性。