[Lv2] JavaScript 運算效能優化:防抖、節流、時間切片
透過防抖、節流、時間切片和 requestAnimationFrame 等技術,優化 JavaScript 運算效能,提升使用者體驗。
問題背景
在平台專案中,使用者會頻繁進行以下操作:
- 🔍 搜尋(輸入關鍵字即時過濾 3000+ 款產品)
- 📜 滾動列表(滾動時追蹤位置、載入更多)
- 🎮 切換分類(篩選顯示特定類型的產品)
- 🎨 動畫效果(平滑滾動、禮物特效)
這些操作如果沒有優化,會導致頁面卡頓、CPU 佔用過高。
策略 1:防抖(Debounce) - 搜尋輸入優化
import { useDebounceFn } from '@vueuse/core';
// 防抖函式:500ms 內如果再次輸入,重新計時
const debounceKeyword = useDebounceFn((keyword) => {
searchGameKeyword(gameState.list, keyword.toLowerCase());
}, 500);
watch(
() => searchState.keyword,
(newValue) => {
debounceKeyword(newValue); // 只在停止輸入 500ms 後執行
}
);
優化前:輸入 "slot game" (9 字元)
- 觸發 9 次搜尋
- 過濾 3000 款遊戲 × 9 次 = 27,000 次運算
- 耗時:約 1.8 秒(頁面卡頓)
優化後:輸入 "slot game"
- 觸發 1 次搜尋(停止輸入後)
- 過濾 3000 款遊戲 × 1 次 = 3,000 次運算
- 耗時:約 0.2 秒
- 效能提升:90%
策略 2:節流(Throttle)— 滾動事件優化
應用場景: 滾動位置追蹤、無限滾動載入
import { throttle } from 'lodash';
// 節流函式:100ms 內只執行 1 次
const handleScroll = throttle(() => {
scrollTop.value = document.documentElement.scrollTop;
}, 100);
window.addEventListener('scroll', handleScroll);
優化前:
- 滾動事件每秒觸發 60 次(60 FPS)
- 每次觸發都計算滾動位置
- 耗時:約 600ms(頁面卡頓)
優化後:
- 滾動事件每秒最多觸發 1 次(100ms 內只執行 1 次)
- 耗時:約 100ms
- 效能提升:90%
策略 3:時間切片(Time Slicing)— 大量資料處理
應用場景:標籤雲、選單組合、3000+ 款遊戲篩選、金流歷史紀錄渲染
// 自定義時間切片函式
function processInBatches(
array: GameList, // 3000 款遊戲
batchSize: number, // 每批處理 200 款
callback: Function
) {
let index = 0;
function processNextBatch() {
if (index >= array.length) return; // 處理完成
const batch = array.slice(index, index + batchSize); // 切片
callback(batch); // 處理這一批
index += batchSize;
setTimeout(processNextBatch, 0); // 下一批放到微任務佇列
}
processNextBatch();
}
使用範例:
function searchGameKeyword(games: GameList, keyword: string) {
searchState.gameList.length = 0;
// 將 3000 款遊戲分成 15 批,每批 200 款
processInBatches(games, 200, (batch) => {
const filteredBatch = batch.filter((game) =>
game.game_name.toLowerCase().includes(keyword)
);
searchState.gameList.push(...filteredBatch);
});
}