在不少筆試面試題中總能看到js函數去抖和函數節流,看過不少關於這二者的討論,最近終於在一個需求中使用了函數去抖(debounce)和函數節流(throttle)。css
須要完成的效果是,鼠標在表格的單元格上時,顯示一個浮動框,而且浮動框會隨鼠標移動。html
這是效果圖,沒有作成動圖,應該都能想象出來:面試
基本效果很容易實現,用單元格的hover事件控制浮動框的顯示;鼠標移出單元格,即mouseout事件觸發浮動框的隱藏;ide
而浮動框跟隨鼠標移動的效果則用mousemove事件,監聽鼠標的位置,同時改變浮動框的位置。函數
直接放公司項目的代碼,懶癌晚期...spa
html結構3d
1.頁面表格code
2.浮動框:htm
3.浮動框的css:對象
注意將浮動框的定位設爲fixed,z-index設大一點,能置於頂層就ok了。其餘樣式根據須要來寫。
js部分
$(document).ready(function(){ //鼠標滑過表格單元格顯示浮動框
var showFloatTimer=null; $('.table-to-float tbody tr td').hover( function(){ clearTimeout(showFloatTimer); showFloatTimer=setTimeout(function(e){ $('.float-wp').fadeIn(200);//浮動框淡出 },300); } ); $('.table-to-float tbody tr td').mouseout(function(){ $('.float-wp').hide(); clearTimeout(showFloatTimer);//鼠標滑出時清除函數去抖中的定時事件
}); $('.table-to-float tbody tr td').mousemove(floatMove());
//floatMove()運行後返回一個函數對象,或什麼都不返回
function floatMove(){//節流函數 var canRun=true; return function(e){//e是mousemove的event參數 if(!canRun){return;}//若是有一個定時方法,直接返回 canRun=false; setTimeout(function(){ var top = e.pageY+15; var left = e.pageX+15; $('.float-wp').css({ 'top' : top + 'px', 'left': left+ 'px' }); console.log("改變浮框位置"); canRun=true; },150); } } });
沒有加函數節流和函數去抖以前,會出現如下問題:
1.當鼠標無心滑過表格單元格時,浮動框也會顯示,每滑過一個單元格閃現一次;
2.快速滑過單元格時,觸發hover事件,可是mouseout事件不會執行,致使浮動框不消失。
3.mousemove監聽頻率高,消耗系統資源。
爲了解決這三個問題,增長了去抖和節流函數
概念:
函數去抖:當動做頻繁觸發時,只觸發最後一次。
函數節流:當動做頻繁觸發時,隔一段時間觸發一次,以下降觸發頻率。
代碼解釋:
所以,解決第一個問題運用了函數去抖,當鼠標停在一個單元格時顯示浮動框,在此以前通過的單元格都不會觸發浮動框顯示事件。
爲了解決第二個問題,對函數去抖的封裝寫法作了一點改動,將顯示浮動框的定時器設爲全局,在鼠標滑出時清除,這樣就保證了滑出以後沒有浮動框能夠再顯示。
第三問題運用函數節流來解決,下降mousemove的觸發頻率
沒有運用函數節流以前,將鼠標滑過一個單元格的高度的距離,函數執行了30次左右
加了節流函數以後,執行次數僅爲7次
在這個地方,被event參數的傳遞困擾了很久,由於沒有意識到 floatMove() 運行以後要麼返回函數對象,要麼返回空
一直在研究如何將event先傳入floatMove內,再傳入回調函數內
冷靜了一下子以後再想一想
$('.table-to-float tbody tr td').mousemove(floatMove());
這樣寫,當 floatMove() 運行返回函數對象時,就至關於直接在mousemove裏寫回調函數,因此直接在floatMove中return函數對象的地方接收參數就能夠了。