debounce
創建一個防抖函數,延遲執行直到停止調用一段時間。
基礎用法
typescript
import { debounce } from 'radash'
const debouncedSearch = debounce(async (query: string) => {
const response = await fetch(`/api/search?q=${query}`)
return response.json()
}, 300)
// 用戶輸入時,只有在停止輸入300ms後才會執行搜索
debouncedSearch('hello')
debouncedSearch('hello world')
debouncedSearch('hello world example')
// 只有最後一次調用會執行
語法
typescript
function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number,
options?: {
immediate?: boolean
}
): (...args: Parameters<T>) => void
參數
fn
(function): 要防抖的函數delay
(number): 延遲時間(毫秒)options
(object, 可選): 配置選項immediate
(boolean, 可選): 是否立即執行第一次調用,默認為false
返回值
返回一個防抖後的函數。
示例
基本防抖
typescript
import { debounce } from 'radash'
const debouncedLog = debounce((message: string) => {
console.log('Debounced:', message)
}, 500)
// 多次快速調用
debouncedLog('hello')
debouncedLog('hello world')
debouncedLog('hello world example')
// 只有最後一次調用會在500ms後執行
搜索輸入防抖
typescript
import { debounce } from 'radash'
const searchInput = document.getElementById('search') as HTMLInputElement
const debouncedSearch = debounce(async (query: string) => {
if (query.length < 2) return
const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`)
const results = await response.json()
displayResults(results)
}, 300)
searchInput.addEventListener('input', (e) => {
const query = (e.target as HTMLInputElement).value
debouncedSearch(query)
})
function displayResults(results: any[]) {
// 顯示搜索結果
console.log('Search results:', results)
}
窗口大小調整防抖
typescript
import { debounce } from 'radash'
const debouncedResize = debounce(() => {
console.log('Window resized to:', window.innerWidth, 'x', window.innerHeight)
// 重新計算布局
recalculateLayout()
}, 250)
window.addEventListener('resize', debouncedResize)
function recalculateLayout() {
// 重新計算頁面布局
console.log('Layout recalculated')
}
表單提交防抖
typescript
import { debounce } from 'radash'
const debouncedSubmit = debounce(async (formData: FormData) => {
try {
const response = await fetch('/api/submit', {
method: 'POST',
body: formData
})
if (!response.ok) {
throw new Error('Submit failed')
}
const result = await response.json()
console.log('Form submitted successfully:', result)
} catch (error) {
console.error('Submit error:', error)
}
}, 1000)
const form = document.getElementById('myForm') as HTMLFormElement
form.addEventListener('submit', (e) => {
e.preventDefault()
const formData = new FormData(form)
debouncedSubmit(formData)
})
立即執行模式
typescript
import { debounce } from 'radash'
const debouncedFunction = debounce((value: string) => {
console.log('Executed with:', value)
}, 500, { immediate: true })
// 第一次調用會立即執行
debouncedFunction('first') // 立即執行
debouncedFunction('second') // 延遲500ms後執行
debouncedFunction('third') // 延遲500ms後執行
API調用防抖
typescript
import { debounce } from 'radash'
const debouncedApiCall = debounce(async (params: any) => {
const response = await fetch('/api/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params)
})
return response.json()
}, 300)
// 在用戶操作時調用
async function handleUserAction() {
const params = { action: 'update', data: { /* ... */ } }
const result = await debouncedApiCall(params)
console.log('API result:', result)
}
滾動事件防抖
typescript
import { debounce } from 'radash'
const debouncedScroll = debounce(() => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
console.log('Scrolled to:', scrollTop)
// 更新滾動指示器
updateScrollIndicator(scrollTop)
}, 100)
window.addEventListener('scroll', debouncedScroll)
function updateScrollIndicator(scrollTop: number) {
const indicator = document.getElementById('scroll-indicator')
if (indicator) {
indicator.style.width = `${(scrollTop / (document.body.scrollHeight - window.innerHeight)) * 100}%`
}
}
鍵盤事件防抖
typescript
import { debounce } from 'radash'
const debouncedKeyPress = debounce((key: string) => {
console.log('Key pressed:', key)
// 處理鍵盤輸入
processKeyInput(key)
}, 200)
document.addEventListener('keydown', (e) => {
debouncedKeyPress(e.key)
})
function processKeyInput(key: string) {
// 處理鍵盤輸入邏輯
console.log('Processing key:', key)
}
鼠標移動防抖
typescript
import { debounce } from 'radash'
const debouncedMouseMove = debounce((x: number, y: number) => {
console.log('Mouse position:', x, y)
// 更新鼠標位置顯示
updateMousePosition(x, y)
}, 50)
document.addEventListener('mousemove', (e) => {
debouncedMouseMove(e.clientX, e.clientY)
})
function updateMousePosition(x: number, y: number) {
const positionElement = document.getElementById('mouse-position')
if (positionElement) {
positionElement.textContent = `X: ${x}, Y: ${y}`
}
}
復雜參數防抖
typescript
import { debounce } from 'radash'
interface SearchParams {
query: string
filters: Record<string, any>
page: number
}
const debouncedSearch = debounce(async (params: SearchParams) => {
const queryString = new URLSearchParams({
q: params.query,
page: params.page.toString(),
...params.filters
}).toString()
const response = await fetch(`/api/search?${queryString}`)
const results = await response.json()
return {
results,
total: results.length,
page: params.page
}
}, 500)
// 使用防抖搜索
async function performSearch() {
const params: SearchParams = {
query: 'javascript',
filters: { category: 'programming', sort: 'relevance' },
page: 1
}
const result = await debouncedSearch(params)
console.log('Search result:', result)
}
取消防抖函數
typescript
import { debounce } from 'radash'
const debouncedFunction = debounce((message: string) => {
console.log('Executed:', message)
}, 1000)
// 調用函數
debouncedFunction('hello')
// 取消延遲執行
// 注意:radash的debounce不直接支持取消,但可以通過重新創建函數來實現
const cancelDebounce = () => {
// 重新創建防抖函數來"取消"之前的調用
const newDebouncedFunction = debounce((message: string) => {
console.log('Executed:', message)
}, 1000)
return newDebouncedFunction
}
多個防抖函數
typescript
import { debounce } from 'radash'
// 創建多個不同延遲的防抖函數
const quickDebounce = debounce((action: string) => {
console.log('Quick action:', action)
}, 100)
const mediumDebounce = debounce((action: string) => {
console.log('Medium action:', action)
}, 500)
const slowDebounce = debounce((action: string) => {
console.log('Slow action:', action)
}, 1000)
// 使用不同的防抖函數
quickDebounce('fast')
mediumDebounce('normal')
slowDebounce('slow')
條件防抖
typescript
import { debounce } from 'radash'
const conditionalDebounce = debounce((value: string, shouldExecute: boolean) => {
if (shouldExecute) {
console.log('Executing with value:', value)
// 執行實際邏輯
processValue(value)
}
}, 300)
function processValue(value: string) {
// 處理值的邏輯
console.log('Processing:', value)
}
// 根據條件決定是否執行
conditionalDebounce('test', true)
conditionalDebounce('skip', false)
conditionalDebounce('execute', true)
注意事項
- 延遲時間: 選擇合適的延遲時間,太短可能無效,太長影響用戶體驗
- 內存洩漏: 防抖函數會保持對原函數的引用
- 立即執行: 使用immediate選項可以立即執行第一次調用
- 異步函數: 防抖函數可以包裝異步函數
- 參數傳遞: 防抖函數會傳遞所有參數給原函數
與其他方法的區別
throttle()
: 限制執行頻率,防抖是延遲執行debounce()
: 等待停止調用後執行- 手動實現: 需要更多代碼和錯誤處理
實際應用場景
- 搜索輸入: 防止頻繁的API調用
- 窗口調整: 優化布局重新計算
- 表單提交: 防止重復提交
- 滾動事件: 優化滾動處理
- 鍵盤事件: 減少鍵盤事件處理頻率