節流和防抖在咱們平時的項目中挺經常使用的,也是面試中常常會被提問的知識點,今天咱們一塊兒來學習一下。html
簡單理解就是:控制函數每隔n秒執行一次。前端
防止用戶高頻率的觸發事件,恰好這個事件又須要處理大量的計算和渲染而帶來的性能問題。面試
這邊咱們以onscroll
來寫個例子,加深理解。瀏覽器
好比有這樣一個場景:咱們須要判斷瀏覽器滾動條滾動到底部的時候去動態加載一些數據,可能咱們直接就會寫上如下的代碼:bash
let obj = document.querySelector('.throttle-test');
let _count = 0;
obj.onscroll = function () {
// 假設已經滾動到底部了,咱們給_count加1。
_count++;
console.log('執行次數:' + _count);
}
複製代碼
咱們來看下瀏覽器的打印結果,看如下gif圖:函數
能夠看到,函數執行了20次,很顯然這並非咱們想要的,由於onscroll
事件並不會等你滾動到底部了再去觸發事件,而是會不間斷的觸發,這就很容易引起一些性能問題,這時候就須要用到節流了。性能
咱們把代碼作下修改:學習
let obj = document.querySelector('.throttle-test');
let _count = 0;
let _canRun = true;
obj.onscroll = function () {
if (!_canRun) {
return false;
}
_canRun = false;
setTimeout(function () {
// 假設已經滾動到底部了,咱們給_count加1。
_count++;
console.log('執行次數:'+_count);
_canRun = true;
}, 500);
}
複製代碼
經過如下gif圖,咱們能夠看到,函數最終只執行了2次。測試
經過一個定時器,咱們控制函數每隔500毫秒再執行一次,大大下降了執行頻率,從而提高性能。動畫
節流跟防抖,它們既有類似之處但又有所不一樣,很容易混淆。這裏經過比喻來加深理解,先來講說節流。
節流的概念能夠想象一下水壩,你建了水壩在河道中,不能讓水流動不了,你只能讓水流慢些。換言之,你不能讓用戶的方法都不執行。(我的比較喜歡這個比喻,由於它很形象的說出了跟防抖的區別。)
控制函數在n秒內只能執行一次,若是用戶在n秒內重複的觸發事件,則從新計時且函數不會被執行,只有等到用戶再也不觸發事件的時候纔去執行一次。
做用跟節流
相似,也是爲了防止用戶高頻率的觸發事件所引起的性能問題。
能夠想象一下作電梯,當有人進入電梯(觸發事件),那電梯將在10秒後出發(執行事件),這時若是又有人進入電梯了(在10秒內再次觸發了事件),咱們又得從新等10秒才能觸發(從新計時)。
有個文本框讓用戶填寫用戶名,當用戶輸入字符時,咱們須要實時發請求到後臺去驗證用戶名是否有重複的。實際上,在加入防抖機制前,用戶輸入helloworld
後,咱們已經發送了10次請求了,很顯然是不可取的。
看代碼:
let obj = document.querySelector('#testInput'); // 獲取文本輸入框
let _count = 0;
obj.onkeyup = function () {
_count++;
console.log('執行次數:' + _count);
}
複製代碼
咱們來給代碼加入防抖機制:
咱們只能假設用戶在停頓n秒內沒有再觸發事件,咱們就斷定用戶已經輸入完成了,這時再發送請求。
看代碼:
let obj = document.querySelector('#testInput');
let timer = null;
let _count = 0;
obj.onkeyup = function () {
clearTimeout(timer); // 清除定時器,從新計時
timer = setTimeout(function () {
_count++;
console.log('執行次數:'+_count);
}, 800);
}
複製代碼
經過動圖,能夠看到,當我一直輸入的時候,事件是不會被觸發的,直到我中止輸入纔會觸發一次。
實現思路:咱們把目標代碼放入到一個定時器裏,若是事件被頻繁的觸發,目標代碼將不會被執行。爲何不執行呢,由於咱們前面加了clearTimeout
。至關於中途不斷的有人進入電梯,電梯又得從新倒計時10秒纔會啓動同樣,直到用戶沒再輸入了(沒人再進入電梯了),這時候目標代碼纔會按照咱們設定的時間再去執行一次(電梯纔會啓動)。
input
,keyup
更頻繁觸發的事件中,如resize
, touchmove
, mousemove
, scroll
。節流
會強制函數以固定的速率執行。所以這個方法比較適合應用於動畫相關的場景。感謝您的閱讀,但願對你有所幫助。文中若是有描述不當的地方,煩請指正,感激涕零。 另外文中所演示的代碼僅用來測試使用,並不適合用在實際開發中,實際開發可使用Lodash
庫中的節流
和防抖
方法,這裏就不貼代碼了,畢竟考慮的比較全面哈。
Lodash
庫的地址:
節流:www.lodashjs.com/docs/4.17.5…
防抖:www.lodashjs.com/docs/4.17.5…
歡迎你們關注個人公衆號前端幫幫忙
,一塊兒交流學習,謝謝~