在很多筆試面試題中總能看到js函數去抖和函數節流,看過很多關於這兩者的討論,最近終於在一個需求中使用了函數去抖(debounce)和函數節流(throttle)。
需要完成的效果是,鼠標在表格的單元格上時,顯示一個浮動框,並且浮動框會隨鼠標移動。
這是效果圖,沒有做成動圖,應該都能想象出來:

基本效果很容易實現,用單元格的hover事件控制浮動框的顯示;鼠標移出單元格,即mouseout事件觸發浮動框的隱藏;
而浮動框跟隨鼠標移動的效果則用mousemove事件,監聽鼠標的位置,同時改變浮動框的位置。
直接放公司項目的代碼,懶癌晚期...
html結構
1.頁面表格

2.浮動框:

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函數對象的地方接收參數就可以了。
