在做一個(gè)網(wǎng)頁(yè)的導(dǎo)航時(shí)遇到這樣一個(gè)坑积瞒,鼠標(biāo)移動(dòng)在導(dǎo)航鏈接上出現(xiàn)導(dǎo)航閃爍的情況
放到任意鏈接上叉弦,導(dǎo)航會(huì)開(kāi)始閃爍丐一。打開(kāi)F12開(kāi)發(fā)者工具發(fā)現(xiàn)出現(xiàn)閃爍的原因在于一個(gè)class="show"不停切換導(dǎo)致的。圖2
代碼的整體思路應(yīng)該是通過(guò)show這個(gè)class來(lái)決定是否顯示透明導(dǎo)航塊淹冰。通過(guò)詢問(wèn)得知這個(gè)懸浮主要用到了css的hover偽類库车,以及mouseover和mouseout事件來(lái)實(shí)現(xiàn)的。由圖看出是切換class引起的bug樱拴,所以排除是hover的問(wèn)題柠衍。直接在代碼里面找到對(duì)應(yīng)的鼠標(biāo)事件。代碼如圖3晶乔。圖4
從上述代碼看出mouseover和mouseout指向同一個(gè)事件珍坊,只是傳遞的參數(shù)不同。當(dāng)傳入true時(shí)正罢,透明導(dǎo)航塊isList判斷為真阵漏,它遍帶有show這個(gè)class。透明導(dǎo)航塊顯示翻具。反之透明導(dǎo)航塊隱藏履怯。showMenu函數(shù)沒(méi)有任何邏輯,直接對(duì)this.isList賦值裆泳。于是猜測(cè)這個(gè)是由于mouseover和mouseout這兩個(gè)鼠標(biāo)事情冒泡引起的叹洲。
于是,我嘗試使用mouseenter和mouseleave事件分別代替mouseover和mouseout事件工禾。因?yàn)槲覀冎酪坏┠砫om元素的子元素被mouseover了运提,它自己也就被mouseover了,而mouseenter卻是物理上的闻葵,即只有你眼睛看到光標(biāo)進(jìn)入了的元素糙捺,才會(huì)觸發(fā)mouseenter事件。換句話說(shuō)mouseenter和mouseleave事件不會(huì)冒泡笙隙,mouseover和mouseout事件會(huì)事件冒泡洪灯。替換鼠標(biāo)事件之后發(fā)現(xiàn),原本的閃爍問(wèn)題有得到緩解,但沒(méi)有完全消失签钩,第一次鼠標(biāo)進(jìn)入還會(huì)閃爍一次掏呼,而之前會(huì)多次閃爍。經(jīng)查發(fā)現(xiàn):mouseenter事件在鼠標(biāo)進(jìn)入某個(gè)元素铅檩,或第一次進(jìn)入這個(gè)元素的某個(gè)子元素時(shí)觸發(fā)憎夷。一旦觸發(fā)后,在mouseleave之前昧旨,鼠標(biāo)在這個(gè)元素的子元素上觸發(fā)mouseenter事件都不會(huì)觸發(fā)這個(gè)元素的mouseenter事件拾给。即:一旦進(jìn)入,在子元素間的mouseenter不算是在本元素上的mouseenter兔沃。而mouseover事件是必然冒泡的蒋得,一旦子元素mouseover了,本元素必然mouseover(除非子元素上禁止冒泡了)乒疏。
知道這確實(shí)是事件冒泡引起的閃爍额衙,這相當(dāng)于鼠標(biāo)進(jìn)入目標(biāo)元素后,執(zhí)行一次mouseover事件怕吴,由于事件冒泡目標(biāo)元素父類同樣會(huì)執(zhí)行一次mouseover事件窍侧。離開(kāi)目標(biāo)元素同樣執(zhí)行不止一次mouseout事件。這相當(dāng)于this.isList的值為true極短的時(shí)間內(nèi)由于事件冒泡this.isList的值會(huì)為false然后再變成true转绷。正是這個(gè)極短的過(guò)程導(dǎo)致了閃爍伟件。
知道了原理之后。我們可以利用setTimeout來(lái)控制mouseout事件的執(zhí)行代碼如圖5
首先我在data里面聲明了一個(gè)timer作為定時(shí)器(圖5中沒(méi)有體現(xiàn)聲明)议经。然后通過(guò)判斷show的值來(lái)決定是顯示還是隱藏透明導(dǎo)航塊锋爪。當(dāng)show的值為false的時(shí)候是隱藏,但是沒(méi)有立刻讓isList的值變成false爸业。而是設(shè)置一個(gè)定時(shí)器讓其在0.5秒之后再賦值為false。而當(dāng)show為true時(shí)清除在show為false聲明的定時(shí)器亏镰。這樣的處理會(huì)使得定時(shí)器還沒(méi)來(lái)得及將isList設(shè)置為false的時(shí)候就被清除了扯旷,也就是來(lái)不及閃爍了。只有在0.5秒后沒(méi)有mouseover事件發(fā)生索抓,isList才會(huì)被設(shè)置為false钧忽,也就是在鼠標(biāo)徹底離開(kāi)導(dǎo)航時(shí),透明導(dǎo)航去才會(huì)隱藏起來(lái)逼肯。至此閃爍問(wèn)題得到解決了耸黑。
在這個(gè)問(wèn)題下還有一點(diǎn)疑惑,就是閃爍問(wèn)題只在360的某些版本中出現(xiàn)篮幢。其他主流瀏覽器并未發(fā)現(xiàn)這個(gè)問(wèn)題大刊。有清楚這個(gè)問(wèn)題的朋友望告知。