原文http://www.cnblogs.com/yexiaochai/archive/2013/04/23/3037064.html
【初窺javascript奧秘之事件冒泡】那些年我們一起冒的泡前言
若是我說會有此文又是因為一次面試的話,我自己都不知道該怎麼形容我的心情了,好似我的所有動力皆來自於面試似的。
其實不是這樣的,我原來一個專案經理對我說,隔一兩個月出去面試下,一來你會知道自己的不足知道怎麼提高,二來你就知道自己漲價沒。
現在回想起來他說的是很對的,面對這次的團隊解散,我反而不那麼著急,因為我不太懼怕面試,走到哪裡都能找到工作,當然這裡沒有鼓勵大家出去面試的意思啦。
回到本文,當時面試官問了我一個問題,我當時就支支吾吾的答不上來,其實細細思考的話這道題還是有點意思的:
在一個div上畫div(絕對位置),然後再在剛剛那個div裡面(上面更合適)畫一個div,現在去拖到div,你知道你拖動的是哪個div嗎?
說這道題本身並不難絕對是騙人的(反正時至今日我都有點沒底...),說他難,他又沒有難到哪裡去,每個人都知道是事件冒泡相關的東西。
還是那句話知道不等於瞭解,瞭解不等於深入,皮毛說不清楚事情,今天讓我們帶著問題一起學習吧!
由於本文是邊學邊寫的,可能會有點亂,可能會有我的唧唧歪歪請各位大哥見諒。
基礎知識
刀不磨不亮,我們先從基礎來,這裡就直接忽略IE的attachEvent了吧,我們說下標準的就是,請看以下代碼(這裡我確實沒臉再用jquery了,原生吧):
基礎事件綁定
我們看到點擊按鈕後,執行點擊事件,其中this便是對應元素,e包含了許多有用資訊比如:
阻止冒泡(e.stopPropagation();)、阻止瀏覽器預設事件(e.preventDefault();)、當前點擊元素、滑鼠位置......
好,我們在此基礎上做一個擴充,我們多增加兩個元素,然後給document綁定事件,最後看看我們點擊的是哪個:
1 <body> 2 <div id="div"> 3 <input id="input" value="點擊我" type="button" /> 4 <ul> 5 <li><a>濕濕的</a></li> 6 <li><a>濕濕的1</a></li> 7 <li><a>濕濕的2</a></li> 8 </ul> 9 <span>安能辨我<b>是</b>雄雌</span>10 </div>11 <script type="text/javascript">12 document.addEventListener('click', function (e) {13 var scope = this;14 var cur_el = e.target.tagName;15 var s = '';16 }, false);17 </script>18 </body>
現在我不論點擊哪個標籤皆會將其標籤名字列印出來,請在s=''處設定斷點查看:
於是我突然感覺知道了什麼,又不能確認,所以我們都不敲板,來捋一捋:
1 我們為根項目綁定點擊事件2 我們點擊按鈕後,按鈕並沒有事件處理,所以將事件向上傳遞,直到document
3 document是綁定了事件的,所以觸發了事件,其中this指向document,但是e中的當前點擊元素卻是按鈕
好,先將一切暫停,我們來做一個很土的選項卡:
醜陋的選項卡
若是現在需要完成一個簡易功能,點擊每個選項卡,內容地區文字便會變成選項卡的標籤文字你會怎麼做呢?
很多年以前,我會使用jquery的標籤選取器為每個li添加事件,我確信我會這樣做,這樣做有幾個問題:
1 事件綁定過多
2 動態添加li標籤的話,是不具備事件的
於是這裡我們就可以用到前面的事件冒泡機制啦:
選項卡代碼完整版
根據這個例子,我相信,各位都對事件冒泡有一個認識了,我們繼續。
絕對位置·亂了的一切
這裡會說到絕對位置,只是因為他比較特殊,其實漂浮、元素之間重疊都有可能讓我們的冒泡變得複雜,先上代碼:
複雜的情況
現在各位還知道自己在幹什麼嗎???這個將情況變的複雜,因為我們必須清晰的知道誰離我最近。
解決問題
到瞭解決問題的時候了,要不我們將最開始出現那道題做了吧?我們先規定一下做法,只能這樣做喲:
1 給一個按鈕給使用者讓使用者選擇現在是畫矩形或者拖動矩形
2 在給定的一個div(相對定位)中畫div,畫的div(絕對位置)將append到父div裡面
3 選擇拖動div,便可在父層div中進行拖動了
4 不能為除父div以為的div添加事件!
5 可以使用jquery,可以暫時不考慮捲軸
怎麼樣簡單吧,讓我們動手吧:
為了方便各位拖到,我先上個圖,然後再來一段醜陋的代碼:
醜陋的代碼
大家去運行看看,就會發現問題了:
我們拖動1時,沒有問題,但是當我們拖到0時,一旦碰到1就會出狀況!!!
這是因為我們mousedown事件是綁定到了父div上,當我們滑鼠點下時,便給個元素繫結了滑動事件,但是在1
上時,因為他離我們近,所以我們不會滑動到0上,。。。。滑動0時碰到1,滑鼠自然就在1
上滑動了,所以拖動的就是1。。。。
我不知道各位暈不暈,我可能有點暈,今天暫時如此了。。。。
師兄討論的結果
剛剛和師兄就這個問題做了一個討論,他的意見還是很中肯的:
我們mousedown的時候便擷取該元素,然後直接給該子項目綁定各種事件,mouseup後便把事件取消,便不會有以上問題了,
另外可能起z-index還需要進行設定,我這裡就不管了:
師兄意見
結語
小弟對冒泡機制理解還是很淺的,若是各位大哥看到此文覺得有什麼不足,或者有什麼問題,請一定指出來哦。
另外那道題建議各位做下,我那個代碼寫得有點水,期待高品質的代碼。。。。
如果你覺得這篇文章還不錯,請幫忙點擊一下推薦,謝謝!