已知:
1.1 開啟Timeout程序: scope.setTimeout("functionName()" | functionHandle, timeValue) 返回值:timerID
1.2 關閉Timeout程序: scope.clearTimeout(timerID);
2.1 開啟Interval程序: scope.setInterval("functionName()" | functionHandle, timeValue) 返回值:timerID
2.2 關閉Interval程序: scope.clearInterval(timerID);
一、背景
在替實驗室小伙伴解決問題過程中,出現了這樣一個問題:
她用網頁做了一個輪播圖,利用不斷地輪詢setTimeout + 切換被輪播圖片的css屬性opacity:0/1來達到輪播效果;
當網頁加載后,圖片輪播自動執行;當用戶鼠標移動到圖片輪播區域上時,立即停止輪播(即 清除 setTimeout定時器),而不是繼續輪播圖片(使用戶看不到想看的圖片內容,提高用戶體驗);
然而,在全局域中,使用clearTimeout()方法可以實現,但在鼠標觸發事件的函數內部調用,卻失敗,百思不得其解!(這個問題,實際上本文並沒有解決!)
為了解決這個需求,我模擬了這一個過程,並對setTimeout輪詢方法與圖片輪播的方法進行解耦(分離成為兩個函數),然后在封裝的輪詢定時器Timer中依次調用圖片輪播方法和setTimeout方法,同時在輪詢過程中,總是記錄最近(最后)一次setTimeout方法返回的timerID值,這一點很重要;
最后:當鼠標滑過目標區域時,通過記錄的最后一次timerID和clearTimeeout值來關閉圖片輪播整個輪詢。
【原理:即關閉最后一次(也是程序執行的最近一次)循環的timeID,使循環停止】
二、源碼
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>demo setTimeout & clearTimeout</title> </head> <body> <ul> <li><a href="#"><input type="number" value="0"></a></li> <li><a href="#"><input type="number" value="1"></a></li> </ul> <script type="text/javascript"> var aNodes = document.getElementsByTagName("a"); var inputNodes = document.getElementsByTagName("input"); //console.log('test:aNodes ' + aNodes.length); var changeNum = function(){ inputNodes[0].value = parseInt(inputNodes[0].value) + 1; }; var a1_timeoutId; var timeIds = -1; var changeNumByTimer = function(){ // a1_timeoutId = setTimeout(function(){ changeNum(); var timeKey = setTimeout("changeNumByTimer()",1000); timeIds = timeKey; console.log('test:當前的timeID:' + timeKey); // timeIds.push(timeKey); // setTimeout(changeNum,1000); // },1000); } changeNumByTimer(); //當鼠標滑過 aNodes[0].onmouseover = function(){ console.log('test:aNodes[0].onmouseover:' + "鼠標滑過a鏈接[0]"); console.log('test:aNodes[0].onmouseover: timeIds ' + timeIds); // for(var i = 0; i < timeIds.length; i++){ // // clearTimeout(timeIds[i]); // // console.log('test: 已經關閉了 timeID:' + timeIds[i]); // //clearTimeout(timeIds[timeIds.length-1]); // //console.log('test: 已經關閉了 timeID:' + timeIds[timeIds.length-1]); // } clearTimeout(timeIds); console.log('test: 已經關閉了 timeID:' + timeIds); } </script> </body> </html>
三、效果
四、總結
1.成功解決了需求的技術問題。
2.其實並沒有解決我們最初的問題:
2.1 為什么全局域中可以關閉,而在onmouseover(鼠標滑過事件)函數中無法關閉的問題
3.參考文檔:
MDN:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval
4.歡迎小伙伴交流這一問題~