由event target引发的关于事件流的一连串思考(二)
阻止事件冒泡
W3C的方法是ev.stopPropagation(),IE則是使用ev.cancelBubble = true。
先不談IE的私有方法,首先討論一個(gè)問題:ev.stopPropagation()真的是阻止事件冒泡嗎?
實(shí)際上,這個(gè)問題需要分兩種情況來討論:
此時(shí)輸出結(jié)果如下:
可以看到阻止事件冒泡成功了,證明DOM0確實(shí)是阻止事件冒泡。此時(shí)點(diǎn)擊內(nèi)層圓,輸出結(jié)果如下:
我們將 ul.addEventListener('click',function(ev){console.log("ul 冒泡"); }); 復(fù)制代碼改為
ul.addEventListener('click',function(ev){console.log("ul 冒泡");ev.stopPropagation(); }); 復(fù)制代碼此時(shí)點(diǎn)擊內(nèi)層圓,輸出結(jié)果如下:
可以看到本來會(huì)冒泡到div上的點(diǎn)擊事件被阻止了,此時(shí)跟DOM0的阻止事件冒泡是一致的。 但是如果我們改為阻止在ul的捕獲事件上阻止事件冒泡的話,事件捕獲還會(huì)進(jìn)行嗎?還是只會(huì)阻止冒泡?我們來測(cè)試一下,將 ul.addEventListener('click',function(ev){console.log("ul 捕獲"); },true); 復(fù)制代碼改為
ul.addEventListener('click',function(ev){console.log("ul 捕獲");ev.stopPropagation(); },true); 復(fù)制代碼此時(shí)的輸出結(jié)果如下:
可以看到,不但冒泡的整個(gè)階段被阻止了,而且li的事件捕獲也被阻止了。所以總結(jié)一下這兩點(diǎn),ev.stopPropagation()不止可以阻止事件冒泡,如果在捕獲階段使用還可以阻止事件捕獲。
那么我們?cè)倏紤]一種特殊情況:如果ev.stopPropagation()在target階段執(zhí)行會(huì)是什么情況,代碼如下。 JavaScript:
div.addEventListener('click',function(){console.log("div 捕獲"); },true); ul.addEventListener('click',function(ev){console.log("ul 捕獲"); },true); li.addEventListener('click',function(ev){console.log("li 捕獲");ev.stopPropagation(); },true); div.addEventListener('click',function(ev){console.log("div 冒泡"); }); ul.addEventListener('click',function(ev){console.log("ul 冒泡"); }); li.addEventListener('click',function(ev){console.log("li 冒泡"); }); 復(fù)制代碼我們?cè)趖arget上阻止了事件監(jiān)聽,這樣整個(gè)事件冒泡應(yīng)該是被阻止的,我們看輸出結(jié)果:
target的冒泡仍然執(zhí)行了,其實(shí)原因很簡(jiǎn)單,我們?cè)谏弦徽乱呀?jīng)提到了,就不多做贅述了。阻止事件冒泡的兼容寫法:
if(event.stopPropagation){event.stopPropagation(); }else{event.cancelBubble = true; } 復(fù)制代碼阻止默認(rèn)事件
這個(gè)沒什么好講的,用于阻止瀏覽器默認(rèn)的事件,比如提交按鈕的點(diǎn)擊默認(rèn)提交,a標(biāo)簽的點(diǎn)擊跳轉(zhuǎn)等。不過之前遇到過一個(gè)問題,在jsp里無法阻止提交按鈕的提交事件,最后還是換成了div然后使用form.submit()提交才通過。 兼容寫法如下:
if(event.preventDefault){// W3C的阻止默認(rèn)事件event.preventDefault(); }else{// IE私有的阻止默認(rèn)事件event.returnValue = false; } 復(fù)制代碼事件流的常見應(yīng)用:事件委托
事件委托就是利用事件冒泡,只指定一個(gè)事件處理程序,就可以管理某一類型的所有事件。
阻止事件冒泡應(yīng)用
有一個(gè)很應(yīng)景的例子,頁面有一個(gè)彈出框,可拖拽,彈出框內(nèi)有一個(gè)input框,這個(gè)框內(nèi)輸入的文字要可以選中。 我們先來實(shí)現(xiàn)頁面結(jié)構(gòu)和拖拽功能,代碼如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Document</title><style>*{margin: 0;padding: 0;}div{position: absolute;width: 300px;height: 100px;background-color: #2578b5;box-sizing: border-box;padding: 30px;}input{width: 100%;line-height: 1.6em;font-size: 16px;}</style> </head> <body><div><input type="text" value="用于復(fù)制的文本"></div><script>var div = document.querySelector('div');var input = document.querySelector('input');div.onmousedown = function(ev){var mouseLeftDiv = ev.clientX - div.offsetLeft;var mouseTopDiv = ev.clientY - div.offsetTop;document.onmousemove = function(ev){var divLeftBody = ev.clientX - mouseLeftDiv;var divTopBody = ev.clientY - mouseTopDiv;var docWidth = document.documentElement.clientWidth;var docHeight = document.documentElement.clientHeight;if(divLeftBody <= 0){divLeftBody = 0;}else if(divLeftBody >= docWidth - div.offsetWidth){divLeftBody = docWidth - div.offsetWidth;};if(divTopBody <= 0){divTopBody = 0;}else if(divTopBody >= docHeight - div.offsetHeight){divTopBody = docHeight - div.offsetHeight;};div.style.left = divLeftBody + 'px';div.style.top = divTopBody + 'px';}document.onmouseup = function(){document.onmousemove = null;}}</script> </body> </html> 復(fù)制代碼此時(shí)頁面如下:
拖拽功能實(shí)現(xiàn)了,但是我們發(fā)現(xiàn)想要復(fù)制文本的時(shí)候,沒有復(fù)制到,反而也觸發(fā)了拖拽功能,這就很尷尬了。這時(shí)我們的阻止事件冒泡就起作用了,我們?cè)趇nput框上阻止mousedown事件冒泡到外層,代碼如下: JavaScript:
input.onmousedown = function(ev){ev.stopPropagation(); } 復(fù)制代碼大功告成,此時(shí)既可以復(fù)制文本,外層又可以拖拽。
參考資料: http://www.cnblogs.com/liugang-vip/p/5616484.html http://www.cnblogs.com/libin-1/p/6368323.html
總結(jié)
以上是生活随笔為你收集整理的由event target引发的关于事件流的一连串思考(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软发布Azure SignalR Se
- 下一篇: OO9-11总结