徹底搞懂JavaScript防抖與節流

今天爲大家帶來一篇JS重難點的知識體系,這也是前端高薪必備的重難點知識,而且防抖與節流在各大企業前端面試過程中經常會考到的高頻面試題!

 

爲了更好的幫助大家理解防抖與節流,我們特意從我們的系統班(星辰班)中節選了兩節課詳細的講解!放在釘釘羣直播回放裏面,大家可以看完這個文章之後,可以通過最底部的微信二維碼添加助理老師,加入三十天計劃羣裏學習!(如果你已經添加了助理老師,那還等什麼,趕緊去問問老師,加入交流羣學習吧!)

有同學反饋:

看了那麼多面試題和答案,還不如老師一節課講的通透,聽了不過癮還想繼續聽 ^_^

 

一、爲什麼需要防抖與節流

我們要了解什麼是防抖與節流?這就需要回歸到現實的應用場景來談。

如果我們要監聽瀏覽器滾動事件,或監聽輸入框值變化查詢搜索結果等等,這些場景有個共同特點,頻繁執行,然而我們不需要太頻繁執行,比如滾動事件,間隔幾百毫秒或者一秒執行回調就能滿足業務需求,所以纔有了節流和防抖的概念,目的是減少事件回調執行,提高瀏覽器性能。

接下來我們通過一個常見的防抖案例:搜索查詢來展開講解,幫助大家理解防抖。然後我們再通過一個常見的節流案例:滾動加載更多來展開講解,幫助大家理解節流。

二、防抖案例:搜索查詢

比如我們在一個表單中輸入內容,JS通過監聽輸入框值的變化來查詢搜索結果,我們會通過keyup事件來處理,當鍵盤彈起時就會觸發keyup事件,在事件處理函數中發送請求處理查詢結果。在我們輸入內容時,會頻繁的觸發keyup事件,然而我們並不希望太頻繁觸發keyup事件處理函數發送請求查詢。我們希望當我們擡起鍵盤間隔幾百毫秒後再觸發keyup事件處理函數發送請求查詢(如果在間隔時間內再次觸發keyup事件,就會把上一次的定時器清除,重新再計時)。因爲頻繁的觸發增加了瀏覽器的性能消耗,同時也增加了對服務器的請求次數,增加服務器的壓力。具體代碼實現如下:

當我們以正常的速度在輸入框中輸入內容時,兩種效果的前後對比

未添加防抖前的效效果

<body>
搜索查詢:<input type="text" id="search" />
<script>
const search = document.getElementById("search");
var i = 0;
search.onkeyup = function () {
//處理查詢內容....
console.log(i++);//每觸發一次,i+1
};
</script>
</body>

 

 

 

添加防抖前的效效果

添加防抖代碼後的效果<body>
搜索查詢:<input type="text" id="search" />
<script>
const search = document.getElementById("search");
var i = 0;
var timer = null;
search.onkeyup = function () {
//如果之前的定時器還在,則清除
if (timer) {
clearTimeout(timer);
}
//在400毫秒後再觸發
timer = setTimeout(function () {
//處理查詢內容...
console.log(i++);
timer = null; //本次查詢完成,則定時器清除,以方便下次查詢處理
}, 400);
};
</script>
</body>

 

>每次鍵盤擡起都會觸發keyup事件,但是keyup事件需要在400ms後纔會處理查詢操作,所以在下次觸發keyup時,時間在400ms內,就會把上一次的定時器給清除了,本質上就沒有觸發查詢操作。所以在所有電話號碼輸入完成後,400ms後就觸發了一次查詢操作。這樣做的好處減少事件回調執行,提高瀏覽器性能。

 

三、什麼是防抖及應用場景

防抖的概念

 

在連續的事件中,只需觸發最後一次回調,也就是將幾次操作合併爲一此操作進行。原理是維護一個計時器,規定在delay(延遲)時間後觸發函數,但是在delay時間內再次觸發的話,就會取消之前的計時器而重新設置。這樣一來,只有最後一次操作能被觸發。

 

應用場景

 

搜索框輸入查詢、手機號、郵箱驗證輸入檢測。只需用戶最後一次輸入完,再發送請求

窗口大小resize。只需窗口調整完成後,計算窗口大小,防止重複渲染。

四、防抖函數的封裝

<script>
   //fn爲事件處理函數   delay延遲時間
   function debounce(fn, delay) {
       var timer = null;
       return function () {
           if (timer) {
               clearTimeout(timer);
          }
           timer = setTimeout(() => {
               fn.apply(this, arguments); //this和參數
               timer = null;
          }, delay);
      };
  }
</script>

五、節流案例:滾動加載更多

接下來我們通過滾動加載更多爲案例來展開講解,幫助大家理解節流。

當我們滾動瀏覽器的滾動條時,會頻繁觸發scroll事件。我們通過監聽瀏覽器scroll事件來斷判斷滾動條位置,如果滾動條滾動到頁面的最底部,則就會加載更多信息。因爲滾動時會頻繁觸發scroll事件,就會造成頻繁的判斷滾動條位置。

而我們並不希望每次觸發scroll事件都需要去判斷滾動條的位置,來決定是否加載更多,我們希望能間隔一定時間(幾百毫秒)再判斷一次,然後決定是否加載更多。如果時間不夠,啥處理也不做,這樣就能減少瀏覽器性能的消耗。

滾動加載更多源理:

  • 可視區的高度 + 滾動條滾動高度 >=文檔高度 (整個滾動高度) 時就觸發加載更多信息

未添加節流處理前的效果

scroll事件函數中的代碼,在scroll事件觸發時會頻繁的被執行,特別消耗性能

<script>
var i = 0;
window.onscroll = function () {
//會頻繁的處理以下代碼,特別消耗性能
console.log(++i);//測試被執行的次數
var scrollTop = document
.documentElement.scrollTop;
var clientHeight = document
.documentElement.clientHeight;
var scrollHeight = document
.documentElement.scrollHeight;
if (scrollTop + clientHeight + 10 >= scrollHeight) {
//滿足以上條件,則加載更多數據
console.log("開始加載更多數據....");
}
};
</script>

 

 

添加節流處理後的效果

 

scroll事件中的代碼,會在事件觸發時,每隔100ms觸發一次。

<script>
var i = 0;
var timer = null;
window.onscroll = function () {
if (timer) {
return;
}
timer = setTimeout(function () {
console.log(++i);//測試被執行的次數
var scrollTop = document
.documentElement.scrollTop;
var clientHeight = document
.documentElement.clientHeight;
var scrollHeight = document
.documentElement.scrollHeight;
if (scrollTop + clientHeight + 10 >= scrollHeight) {
//滿足以上條件,則加載更多數據
console.log("開始加載更多數據....");
}
timer = null;
}, 100);
};
</script>

同樣的佈局,同樣的效果,在未做節流處理和做了節流處理,兩者效果上有很大的差異。從頭部滾動到底部觸發加載更多,未做節流處理,共觸發了35次代碼的執行,而做了節流處理的,只觸發了6次代碼的執行。

 

 

六、什麼是節流及應用場景

什麼是節流

使得一定時間內只觸發一次函數。原理是通過判斷是否到達一定時間來觸發函數。

節流應用場景

監聽滾動事件判斷是否到頁面底部自動加載更多

搜索聯想功能

DOM元素的拖拽功能實現

射擊遊戲的 mousedown/keydown 事件(單位時間只能發射一顆子彈)

防止高頻點擊提交,防止表單重複提交;

 

七、節流函數的封裝

<script>
   function throttle(fn, delay) {
       var timer = null;
       return function () {
           if (timer) {
               return;
          }
           timer = setTimeout(() => {
               fn.apply(this, arguments);//把this和參數傳遞過去
               timer = null;
          }, delay);
      };
  }
</script>

八、總結防抖與節流

不同點

 

節流不管事件觸發有多頻繁,都會保證在規定時間內一定會執行一次真正的事件處理函數

防抖只是在最後一次事件後才觸發一次函數。

應用場景

 

防抖應用場景

搜索框輸入查詢、手機號、郵箱驗證輸入檢測。只需用戶最後一次輸入完,再發送請求

窗口大小resize。只需窗口調整完成後,計算窗口大小,防止重複渲染。

節流應用場景

監聽滾動事件判斷是否到頁面底部自動加載更多

搜索聯想功能

DOM元素的拖拽功能實現

射擊遊戲的 mousedown/keydown 事件(單位時間只能發射一顆子彈)

防止高頻點擊提交,防止表單重複提交;

 

相同點

 

都可以通過使用 setTimeout 實現

降低迴調執行頻率。節省計算資源


防抖節流是JS階段重要的教學內容,如果你正在學習JS或者已經在我們的三十天計劃中完成了4個綜合項目實戰,那不妨可以聽下這個課程體系,三十天計劃羣裏還提供了算法、數組等知識體系!

 

 

 

更多完整JavaScript課程體系在我們的系統班裏有完整的呈現,包含了JavaScript基礎篇、重點、算法、原理、面試題、實戰案例講解!同時也爲你提供了前端高級工程師成長體系!(詳細看下圖內容)

 

如果需要深度學習的同學可以點擊下方鏈接瞭解詳細的課程以及課程的報名方式!(,可以先領取以上推薦的幾節JS課程學習,再來參與系統學習,不定期會推出活動,有大額優惠券推出,活動詳情聯繫助理老師瞭解即可!)

Web 前端高級工程師系統課 | arry老師的博客-艾編程

如果你纔開始學習前端,那麼可以先學習我們的三十天計劃(零基礎的同學報名系統班同學可以和老師溝通制定學習計劃,可以得到更快的成長!)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章