理解mouseover和mouseout“不穩定”的原因

Sneezry發表於2015-08-17

原文地址:https://sneezry.com/#!/2015/08/16/理解mouseover和mouseout“不穩定”的原因

謝絕轉載。

事情的起因是博主負責的專案需要一個精美的滑塊供使用者調整圖片大小,當然HTML5有現成的range控制元件博主是清楚的,但前端攻城獅如果做起來都那麼愜意怎麼會成為瀕危物種呢?沒錯,相容性,我們要相容性,作為一個有情懷公司的員工,我們不會像某付寶那樣放棄1%的使用者!不會!

那麼多了不說,直接上博主第一版的程式碼(僅做例項使用,與博主所負責專案的真實程式碼與外觀不同):

See the Pen aOrOj by Li Zhe (@Sneezry) on CodePen

是不是很難用!那個滑塊根本不跟著滑鼠走啊,十分地卡頓!這不是一個有情懷的公司應該做出來的東西!為了避免有些初入前端的同學看不太懂上面的程式碼,我來簡單帶著大家分析一下。HTML和CSS就不說了,我們直接來看看JS的邏輯。

首先滑塊控制把手scrollHandle監聽了mousedown事件,這樣當使用者滑鼠在滑塊上按下後就看著監視滑鼠的活動情況。mouseupmouseout事件都繫結在了更大的scroll元素是為了避免使用者滑鼠移動速度過快移出scrollHandle元素導致事件捕捉失敗。

博主在寫完程式碼之後感覺邏輯完美得無懈可擊,甚至專門設計了一個區域更大的scroll元素來提高事件捕捉的可靠性,可是事實呢!事實讓博主甚是崩潰啊!怎麼回事!

為了確定問題所在,博主將監聽事件的結果輸出到控制檯,結果發現,當使用者滑鼠移出scrollHanlde時,scrollmouseout事件被觸發了,但隨後立刻又觸發了scrollmouseover事件!這讓博主一度認為是瀏覽器的Bug——沒事你在那mouseoutmouseover的幹啥!但最後證明其實是博主術業不精,對此博主深表愧疚,所以博主事後將W3C上Level 3 DOM Events從頭到尾看了一遍。

我相信,對DOM Events瞭解不夠深入的同學遇到這個問題第一感覺一定也認為是瀏覽器出了問題,因為mouseoutmouseover同時被觸發是不合邏輯的。那麼博主來和大家一同分析一下這件“詭異”事件是如何發生的。

DOM Events中有個屬性叫bubbles,翻譯過來叫冒泡。這個屬性名看起來很有趣,感覺也有些抽象,但實際上它恰恰生動形象地表達了這個屬性的意思。冒泡屬性來說明這個事件是否會向下傳遞,這個性質我相信在很多事件中同學們都或多或少知道,但可能單獨提出來同學們對不上號。比如click事件,當點選一個元素時,此元素的父系元素也會接收到點選事件,這就是因為子元素的click事件為冒泡事件,會傳遞給其父系元素。而bubbles這個詞形象地描述出這個過程好比水中的氣泡從水底慢慢上浮,只是DOM Events方向相反,傳遞是從頂向下的,直到傳遞到bodyhtmlwindow(這三者是傳遞鏈中的最後三個,不是並列關係)。

那麼上例的scroll元素被瀏覽器折騰得反覆收到mouseoutmouseout事件就不奇怪了,首先滑鼠移出了scrollHandlescrollHandle接收到了mouseout事件,由於這個事件是冒泡的,隨後便傳給了scroll,於是scroll接收到了mouseout事件;之後滑鼠移到了灰色或者藍色進度條上,或者直接移動到了scroll上,無論三者中的哪一個,scroll都會因為冒泡接收到mouseover事件。這就是看起來在上例中mouseovermouseout“不穩定”的原因。

那麼冒泡事件還有哪些呢?通過 W3C文件 可以知道,冒泡事件還有beforeinputclickcompositionstartcompositionupdatecompositionenddbclickfocusinfocusoutinputkeydownkeyupmousedownmousemovemouseupselectwheel

問題的原理搞懂了,那麼應該如何解決呢?首先所有冒泡事件在傳遞的過程中,target都是不變的,所以可以直接在scrollmouseout事件中判斷e.target === this來過濾其子元素傳遞過來mouseout事件。等等,這不是正規的解決方法!W3C顯然考慮到了博主在開始說明的使用背景,所以有專門的事件來處理這個問題——mouseentermouseleave,這兩個事件不冒泡,是我們真正需要用到的方法。或許諸位同學又有疑問了,“你前面不是說有情懷的公司不放棄1%的使用者,要做到相容性嗎,這個新標準相容性可以接受嗎,IE全家你問過了嗎”,您還別說,這兩個事件正是IE發明的,IE全家都支援,甚至包括IE6!所以嘛,不用總吐槽人家小軟就會添亂,人家真的給W3C提交了很多有價值的建議標準呢!

下面是改後的Demo,用起來是不是舒爽多了!

See the Pen Pqvqvy by Li Zhe (@Sneezry) on CodePen

相關文章