給我解釋下 前端開發中的防抖和節流 并舉個具體的例子
防抖(Debounce)與節流(Throttle)詳解
在前端開發中,防抖(Debounce)?和?節流(Throttle)?是兩種優化高頻觸發事件的技術,用于提升性能和用戶體驗。它們的核心區別在于:
- 防抖:將多次觸發合并為一次執行(只執行最后一次)。
- 節流:限制事件執行頻率(按固定間隔執行)。
防抖(Debounce)
原理
- 在事件被觸發后,延遲?
n
?毫秒再執行回調。 - 如果在這?
n
?毫秒內再次觸發事件,則重新計時。
適用場景
- 搜索框實時聯想(用戶停止輸入后再請求)。
- 窗口 resize 事件(只在調整結束后計算布局)。
- 按鈕提交防止重復點擊。
代碼示例
javascript
// 防抖函數(非立即執行版)
function debounce(fn, delay) {let timer = null;return function(...args) {// 清除上一次定時器if (timer) clearTimeout(timer);// 重新設置定時器,延遲執行timer = setTimeout(() => {fn.apply(this, args);}, delay);};
}// 使用示例
const searchInput = document.getElementById('search-input');
searchInput.addEventListener('input', debounce((e) => {console.log('搜索:', e.target.value);// 發送搜索請求...
}, 300));
節流(Throttle)
原理
- 限制一個函數在一定時間內只能執行一次。
- 即使在這段時間內多次觸發事件,也只會按固定間隔執行。
適用場景
- 滾動加載更多數據(每滾動一定距離觸發一次)。
- 高頻點擊按鈕(如點贊、提交)。
- 游戲中的技能冷卻。
代碼示例
javascript
// 節流函數(時間戳版)
function throttle(fn, limit) {let lastExecTime = 0;return function(...args) {const now = Date.now();// 如果距離上次執行超過限制時間,則執行if (now - lastExecTime > limit) {fn.apply(this, args);lastExecTime = now;}};
}// 使用示例
window.addEventListener('scroll', throttle(() => {console.log('滾動位置:', window.scrollY);// 檢查是否需要加載更多數據...
}, 200));
對比與選擇
特性 | 防抖(Debounce) | 節流(Throttle) |
---|---|---|
執行時機 | 只在最后一次事件觸發后執行 | 按固定間隔執行 |
高頻觸發 | 只執行一次 | 按頻率執行多次 |
應用場景 | 搜索聯想、窗口 resize、防止重復提交 | 滾動加載、高頻點擊、游戲技能冷卻 |
實現方式 | 定時器 | 時間戳或定時器 |
高級實現(帶配置選項)
防抖(支持立即執行)
javascript
function debounce(func, wait, immediate = false) {let timeout;return function() {const context = this;const args = arguments;const later = () => {timeout = null;if (!immediate) func.apply(context, args);};const callNow = immediate && !timeout;clearTimeout(timeout);timeout = setTimeout(later, wait);if (callNow) func.apply(context, args);};
}
節流(結合時間戳和定時器)
javascript
function throttle(func, limit) {let timeout;let lastExecTime = 0;return function() {const context = this;const args = arguments;const now = Date.now();const remaining = limit - (now - lastExecTime);if (remaining <= 0) {// 如果超過限制時間,立即執行if (timeout) {clearTimeout(timeout);timeout = null;}func.apply(context, args);lastExecTime = now;} else if (!timeout) {// 否則,等待剩余時間后執行timeout = setTimeout(() => {func.apply(context, args);lastExecTime = Date.now();timeout = null;}, remaining);}};
}
實際應用示例
1. 搜索框防抖
javascript
const searchInput = document.getElementById('search-input');searchInput.addEventListener('input', debounce((e) => {// 300ms 內沒有新輸入時才發送請求fetch(`/api/search?q=${e.target.value}`).then(res => res.json()).then(data => renderResults(data));
}, 300));
2. 滾動加載節流
javascript
window.addEventListener('scroll', throttle(() => {// 每 200ms 檢查一次是否需要加載更多if (isScrollAtBottom()) {loadMoreData();}
}, 200));
3. 按鈕點擊防抖
javascript
const submitBtn = document.getElementById('submit-btn');submitBtn.addEventListener('click', debounce(() => {// 防止重復提交,2秒內只執行一次submitForm();
}, 2000, true)); // 立即執行版,點擊后先執行,2秒內不再執行
總結
- 防抖:適合需要合并多次觸發的場景,避免不必要的計算或請求。
- 節流:適合需要限制執行頻率的場景,如滾動、拖拽等高頻事件。
合理使用這兩種技術可以顯著提升應用性能,減少資源浪費,改善用戶體驗