應(yīng)用場景
我們經(jīng)常需要監(jiān)聽滾動條滾動或者鼠標(biāo)的移動,但瀏覽器觸發(fā)這類事件的頻率非常高,可能在10幾毫秒就觸發(fā)一次,如果我們處理事件的函數(shù)需要操作大范圍的DOM,這對于瀏覽器的性能是個考驗(yàn),可能像chrome瀏覽器這樣優(yōu)秀的瀏覽器會好一點(diǎn),但放到老版本的IE下,就可能發(fā)生卡頓現(xiàn)象。有的時候,我們只需要處理函數(shù)執(zhí)行一次,比如文本輸入驗(yàn)證,執(zhí)行多次處理函數(shù)反而沒有必要。
所以我們得想個辦法,減少DOM操作的頻度,也就是說稀釋處理函數(shù)的執(zhí)行頻率,解決方法就是函數(shù)防抖和函數(shù)分流。函數(shù)防抖表示只執(zhí)行一次處理函數(shù),函數(shù)分流指降低處理函數(shù)的執(zhí)行頻率,下面是具體解釋。
函數(shù)防抖
函數(shù)防抖指的是多次觸發(fā)事件后,事件處理函數(shù)只執(zhí)行一次,而且是在事件觸發(fā)操作停止的時候。具體的思路就是延遲處理函數(shù),如果設(shè)定的時間到來之前,又一次觸發(fā)了事件,就清除上一次的定時器,具體代碼實(shí)現(xiàn)如下。
var obj = document.getElementById('handle');/** * 事件觸發(fā)的操作 */function myFun() { console.log('throttleV1'); }/** * 不封裝的方法 */obj.onmousemove = function () { clearTimeout(myFun.timer); myFun.timer = setTimeout(myFun,50); }
這里有一個保存timer的技巧,如果不保存timer,那么執(zhí)行完事件處理函數(shù)后,timer將被銷毀,我們也就無法再清楚定時器了,所以需要保存這個變量,即使它所在的函數(shù)作用域?qū)?yīng)的函數(shù)已經(jīng)執(zhí)行完了。這里用到的技巧是把timer設(shè)置為外部函數(shù)的屬性,這樣就不會被銷毀了。
我們還可以對這個方法進(jìn)行封裝。
/** * 封裝的方法之幫頂函數(shù) * @param method * @param delay * @param context */funct