防抖和節流函數是工作中兩種常用的前端性能優化函數,今天我就來總結一下什麼是防抖和節流,並詳細説明一下如何在工作中應用防抖和節流函數
什麼是防抖和節流?
在 JavaScript 中,防抖(debounce)和節流(throttle)是用來限制函數執行頻率的兩種常見技術。
防抖(debounce) 是指在某個時間段內,只執行最後一次觸發的函數調用。如果在這個時間段內再次觸發該函數,會重新計時,直到等待時間結束才會執行函數。
這個技術通常用於處理頻繁觸發的事件,比如窗口大小調整、搜索框輸入等。防抖可以避免函數執行過多次,以減少網絡開銷和性能負擔。
節流(throttle) 是指在一段時間內限制函數的執行頻率,保證一定時間內只執行一次函數調用。無論觸發頻率多高,都會在指定時間間隔內執行一次函數。
這個技術通常用於處理連續觸發的事件,比如滾動事件、鼠標移動事件等。節流可以控制函數的執行頻率,以減少資源消耗和提高性能。
手寫一個防抖的工具函數
function debounce(func, delay) {
let timeoutId;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
func.apply(context, args);
}, delay);
};
}
函數説明
- 這個防抖函數接受兩個參數:
func表示需要進行防抖的函數,delay表示延遲的時間間隔(以毫秒為單位) - 函數內部使用了一個
timeoutId變量來保存定時器的標識。當調用防抖函數返回的新函數時,會清除之前的定時器,並設置一個新的定時器。只有在延遲時間內沒有再次調用該新函數時,才會觸發最終的函數執行
使用示例
該示例表示在全局滾動事件中使用防抖函數,每200毫秒內如果觸發滾動事件,那麼不會執行handleScroll()函數。
然後重新計時200毫秒,再次判斷,直到最後一個200毫秒內沒有觸發滾動事件,才會執行handleScroll()函數
function handleScroll() {
console.log('Scrolled');
}
const debouncedScroll = debounce(handleScroll, 200);
window.addEventListener('scroll', debouncedScroll);
手寫一個節流的工具函數
function throttle(func, delay) {
let timeoutId;
let lastExecTime = 0;
return function(...args) {
const currentTime = Date.now();
const remainingTime = delay - (currentTime - lastExecTime);
clearTimeout(timeoutId);
if (remainingTime <= 0) {
func.apply(this, args);
lastExecTime = currentTime;
} else {
timeoutId = setTimeout(() => {
func.apply(this, args);
lastExecTime = Date.now();
}, remainingTime);
}
};
}
函數説明
- 這個節流函數接受兩個參數:
func是要執行的函數,delay是延遲時間(以毫秒為單位) - 它返回一個新的函數,該函數在調用時會根據指定的延遲時間來限制原始函數的執行頻率
使用示例
在全局滾動事件中使用節流函數,無論在滾動事件的監聽過程中,觸發了幾次handleScroll()函數,都只會在每200毫秒內執行一次handleScroll()函數。
function handleScroll() {
console.log('Scrolled');
}
const throttledScroll = throttle(handleScroll, 200);
window.addEventListener('scroll', throttledScroll);
如何在工作中應用防抖和節流
防抖和節流主要應用於:搜索框輸入事件監聽、窗口大小調整事件監聽、按鈕點擊事件監聽、滾動事件監聽、鼠標移動事件監聽等等場景。
工作中哪些場景可以使用防抖函數?
- 用户輸入: 當用户在表單輸入框中頻繁輸入時,可以使用防抖函數來延遲處理用户輸入,避免頻繁的請求或操作,提高性能和用户體驗。
- 搜索框: 在搜索框中,當用户連續輸入關鍵字時,可以使用防抖函數來延遲發送搜索請求,以避免請求過多。
- 窗口調整: 當窗口大小調整時,會觸發resize事件,可以使用防抖函數來限制resize事件的觸發次數,避免頻繁執行調整相關的代碼。
- 按鈕頻繁點擊: 當按鈕被頻繁點擊時,可以使用防抖函數來限制按鈕點擊的觸發次數。
工作中哪些場景可以使用節流函數?
- 用户輸入: 當用户在文本框中輸入時,觸發搜索功能。使用節流函數可以限制搜索請求的頻率,以避免頻繁的網絡請求。例如,可以設置一個定時器,在用户輸入後的一小段時間內不觸發搜索請求,只在定時器結束後才進行搜索。
- 無限加載: 當用户滾動頁面時,觸發加載更多數據的操作。使用節流函數可以限制加載操作的頻率,以提高頁面的響應性能。例如,可以設置一個定時器,在用户滾動過程中只觸發加載操作的最後一次滾動事件。
- 按鈕頻繁點擊: 當用户頻繁點擊某個按鈕時,觸發某個操作。使用節流函數可以限制點擊操作的頻率,以避免重複操作或者混亂的界面狀態。例如,可以設置一個定時器,在用户點擊後的一小段時間內不觸發重複操作。
如何使用loadsh.js工具庫中的防抖和節流函數
實際開發過程中,我們的項目中可能會直接使用loadsh.js工具庫,來避免重複造輪子,所以這裏也特地説明一下如何使用loadsh.js工具庫中的防抖和節流函數
-
安裝
loadsh.js工具庫npm install lodash -
在項目中引入
loadsh.js工具庫,不同前端項目引入方式不同,請自行鑑別import { debounce, throttle } from 'loadsh'; -
使用防抖函數,該示例中,
submitData()函數被限制為每1秒只會執行最後一次,如果在等待時間內多次調用該函數,則會重置1秒的等待時間// 定義要延遲執行的函數 function submitData(data) { console.log('保存數據:', data); } // 使用debounce函數創建一個延遲執行的函數 const debouncedFn = _.debounce(submitData, 1000); // 模擬連續觸發保存數據的操作 // 等待1秒後,只會執行最後一次保存數據的操作 debouncedFn('數據1'); // 不會輸出 debouncedFn('數據2'); // 不會輸出 debouncedFn('數據3'); // 輸出 —— 保存數據:數據3 -
使用節流函數,該示例中,
throttledFn()函數被限制為每秒只能執行一次,如果在等待時間內多次調用該函數,則不會執行// 定義要減少調用次數的函數 function fetchData(data) { console.log('拉取數據:', data); } // 使用throttle函數創建一個定時執行的函數 const throttledFn = _.throttle(fetchData, 2000); // 調用throttledFn函數 throttledFn('數據1'); // 輸出 —— 拉取數據: 數據1 // 在1秒內多次調用throttledFn函數 throttledFn('數據2'); // 不會輸出 // 2秒後再次調用throttledFn函數 setTimeout(() => { throttledFn('數據3'); // 輸出 —— 拉取數據: 數據3 }, 1000);
我是 fx67ll.com,如果您發現本文有什麼錯誤,歡迎在評論區討論指正,感謝您的閲讀!
如果您喜歡這篇文章,歡迎訪問我的 本文github倉庫地址,為我點一顆Star,Thanks~ :)
轉發請註明參考文章地址,非常感謝!!!