?
在前端開發中,我們經常會遇到這樣的情況:某些事件(如滾動、輸入、點擊等)會頻繁觸發,如果不加以控制,可能會導致性能問題。Vue3 中的防抖(Debounce)和節流(Throttle)就是用來解決這類問題的兩種常用技術。
一、什么是防抖和節流?
1. 防抖(Debounce)
什么是防抖?
??就像我們按電梯按鈕,不管你按多少次,電梯只會在你松手一段時間后才會啟動。
??當事件觸發時,不立即執行處理函數,而是等待一段時間(比如300ms)。如果在這段時間內事件再次觸發,則重新計時。只有在指定時間內事件不再觸發,才會真正執行處理函數。
??適用場景??:
1、搜索框輸入聯想(避免每次按鍵都發送請求)
2、窗口大小調整事件
3、按鈕點擊防重復提交
2. 節流(Throttle)
什么是節流?
當我們滾動頁面時,可能需要執行某些操作,比如懶加載圖片、檢測滾動位置等。如果不加限制,滾動事件會非常頻繁地觸發,導致性能問題。
在固定的時間間隔內(比如300ms),無論事件觸發多少次,處理函數只會執行一次。
適用場景??:
1、滾動事件
2、鼠標移動事件
3、游戲中的連續按鍵處理
二、簡單實現
1. 防抖的簡單實現
function debounce(func, delay) {let timer = null;return function(...args) {// 如果已經有計時器,先清除if (timer) clearTimeout(timer);// 設置新計時器timer = setTimeout(() => {func.apply(this, args);timer = null; // 執行后重置}, delay);}
}
??Vue3 組件示例??:
<script setup>
import { ref } from 'vue';const searchQuery = ref('');// 創建防抖函數
const debouncedSearch = debounce((query) => {console.log('執行搜索:', query);// 這里可以調用API
}, 500);const handleInput = (e) => {searchQuery.value = e.target.value;debouncedSearch(searchQuery.value);
};
</script>
<template><input @input="handleInput" placeholder="搜索..." />
</template>
2. 節流的簡單實現
function throttle(func, delay) {let lastTime = 0;return function(...args) {const now = Date.now();if (now - lastTime >= delay) {func.apply(this, args);lastTime = now;}}
}
??Vue3 組件示例??:
<script setup>
import { ref } from 'vue';const scrollPosition = ref(0);// 創建節流函數
const throttledScroll = throttle(() => {scrollPosition.value = window.scrollY;console.log('滾動位置:', scrollPosition.value);
}, 200);const handleScroll = (e) => {throttledScroll();
};
</script>
<template><div @scroll="handleScroll" style="height: 200px; overflow-y: scroll;"><!-- 很多內容 --><div v-for="i in 100" :key="i">內容 {{ i }}</div></div>
</template>
三、更健壯的實現(包含取消功能)
實際開發中,我們可能需要取消防抖/節流操作,比如組件卸載時清理定時器。
1. 帶取消功能的防抖
function debounce(func, delay) {let timer = null;// 返回一個函數對象,包含執行方法和取消方法const debounced = function(...args) {if (timer) clearTimeout(timer);timer = setTimeout(() => {func.apply(this, args);}, delay);};// 添加取消方法debounced.cancel = function() {clearTimeout(timer);timer = null;};return debounced;
}
??Vue3 組件中使用??:
<script setup>
import { onUnmounted, ref } from 'vue';const searchQuery = ref('');
let debouncedSearch = null;onUnmounted(() => {// 組件卸載時取消防抖if (debouncedSearch) debouncedSearch.cancel();
});debouncedSearch = debounce((query) => {console.log('執行搜索:', query);// 這里可以調用API
}, 500);const handleInput = (e) => {searchQuery.value = e.target.value;debouncedSearch(searchQuery.value);
};
</script>
四、使用 Lodash 庫
如果你不介意使用第三方庫,Lodash 提供了更完善的實現:
npm install lodash
或
yarn add lodash
??使用示例??:
import { debounce, throttle } from 'lodash';// 防抖
const debouncedFn = debounce(() => {console.log('防抖執行');
}, 300);// 節流
const throttledFn = throttle(() => {console.log('節流執行');
}, 300);
??Vue3 中使用??:
<script setup>
import { onUnmounted } from 'vue';
import { debounce } from 'lodash';const handleSearch = debounce((query) => {console.log('搜索:', query);
}, 300);const onInput = (e) => {handleSearch(e.target.value);
};onUnmounted(() => {// 取消防抖handleSearch.cancel();
});
</script>
五、總結
1、什么時候用防抖?什么時候用節流?
使用防抖:
1、用戶停止輸入后再搜索(搜索框)
2、窗口大小調整完成后再調整布局
3、按鈕點擊防止重復提交
使用節流:
1、滾動事件(如無限滾動加載)
2、鼠標移動事件(如拖拽操作)
3、游戲中的連續按鍵
特性區別
特性 | 防抖 | 節流 |
---|---|---|
觸發時機?? | 事件停止觸發后一段時間執行 | 固定時間間隔內最多執行一次 |
行為 | 重置計時器 | 固定間隔執行 |