通常我們對於 .hover 這個事件的印象,就如同於 .mouseenter
與 .mouseleave
這兩個事件的合體。這種互動式(Interaction Helpers)的事件在 jQuery 中還有一個,叫做 .toggle
,在這裡就暫且不提。
一般來說,我們使用 .hover
的時候,就是希望能夠監聽使用者的滑鼠動作,然後在某種條件下觸發事件。那麼,最簡單的例子就是這樣
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-Type" content="text/html; charset=utf-8" />
<title>hover test</title>
<style type="text/css">
<!--
#hover_one {
width: 100px;
height: 100px;
border: 1px solid #efefef;
background-color: #333333;
opacity: 1;
color: #ffffff;
}
-->
</style>
</head>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript">
//<![CDDA[
$(document).ready(function() {
$('#hover_one').hover(function() {
$(this).animate({ 'opacity':0.5 });
}, function() {
$(this).animate({ 'opacity':1 });
});
});
//]]>
</script>
<body>
<div id="container">
<div id="hover_one">Mouse Enter/Leave Here.</div>
</div>
</body>
</html>
我們把這個東西放到 Chrome 中實作,當你在區塊中將滑鼠移入(mouseenter
)與移出(mouseleave
)的時候,他會改變該區塊的透明度。也許你會問,這樣有甚麼問題?其實是有的,當你快速的在該區塊移入移出的時候,你就會發現問題在哪裡了。
發現了嗎?當你的滑鼠在快速移入移出的時候,.hover 會很誠實的把你移動所觸發的事件全部做完,這是好事,但是其中所使用的動態效果,在滑鼠結束移動之後還是繼續作用,這就不一定是好事了。
範例中的方格,就像是著猴(台語)一樣猛閃!
我們由 .hover 特性可以得知,他會很忠誠的,將所觸發的事件的總次數給做完,但是由於觸發事件中,包含了 animate 的動態效果(Fade 之類的效果亦同),這些動態效果都有所謂的執行時間差,在 .hover 快速且重複性的呼叫下,animate 也很誠實的,將每一個步驟全部做完之後,才會結束。
事實上,我們有時候不希望 animate 那麼老實做完所有的事情,所以,我們可以用 stop()
來干涉他!
/// 請直接修改上述例子,加入 stop() 干涉!
$('#hover_one').hover(function() {
$(this).stop().animate({ 'opacity':0.5 });
}, function() {
$(this).stop().animate({ 'opacity':1 });
});
差異很明顯就出現了,在滑鼠快速移入移出的時候,Animate 因為受到 stop()
的干涉,所以並不會做完上一個動作,為什麼說是上一個動作?我們把 .hover
的 fnIn
與 fnOut
拆成循序的清單開來看:
- 滑鼠移入
- 呼叫 stop()
- 停止物件本身所有 animate 效果
- 呼叫 animate()
- 執行物件本身 animate 效果
- 滑鼠移出
- 呼叫 stop()
- 停止物件本身所有 animate 效果
- 呼叫 animate()
- 行物件本身 animate 效果
從 1. 滑鼠移入開始看,由於一開始物件並沒有任何動態效果,所以 stop() 其實等於沒有做事,然後,待等到 6. 滑鼠移出後,此時 7. 所呼叫的 stop() 就有效果了,8. 所停止的動態效果,其實是由 4. 的呼叫所產生,這也是為什麼我說他是干涉上一個動作的原因。
以任何的動態效果來說,使用 stop()
是可以有效的干涉其進行的步驟,對於 .hover
本身其實並沒有影響,以 .hover
的角度來看,他還是不斷的去執行 fnIn
與 fnOut
的動作。所以,倘若你要在 .hover
中呼叫其他的函式,最好還是使用旗標的方式來註記目前的執行狀態是 fnIn
還是 fnOut
,避免重覆大量的呼叫而造成無法預期的結果。
stop()
還可以傳兩個參數,cleanQueue
與 jumpToEnd
,你可以自行試試看。