实现
// debounceRef.js
import { customRef } from 'vue'
/**
* 防抖自定义ref
* @param {any} initialValue 初始值
* @param {number} delay 延迟时间(毫秒),默认200ms
* @param {boolean} immediate 是否立即执行,默认false
* @returns {import('vue').Ref}
*/
export function useDebounceRef(initialValue, delay = 200, immediate = false) {
let timeout = null
let shouldCallImmediate = immediate
return customRef((track, trigger) => {
return {
get() {
track() // 追踪依赖
return initialValue
},
set(newValue) {
clearTimeout(timeout)
// 立即执行模式
if (shouldCallImmediate) {
initialValue = newValue
trigger() // 触发更新
shouldCallImmediate = false
return
}
timeout = setTimeout(() => {
initialValue = newValue
trigger() // 触发更新
shouldCallImmediate = immediate
}, delay)
}
}
})
}
TS 版
// debounceRef.ts
import { customRef, type Ref } from 'vue'
/**
* 防抖自定义ref
* @param initialValue 初始值
* @param delay 延迟时间(毫秒),默认200ms
* @param immediate 是否立即执行,默认false
*/
export function useDebounceRef<T>(
initialValue: T,
delay = 200,
immediate = false
): Ref<T> {
let timeout: ReturnType<typeof setTimeout> | null = null
let shouldCallImmediate = immediate
return customRef<T>((track, trigger) => {
return {
get() {
track()
return initialValue
},
set(newValue: T) {
if (timeout) {
clearTimeout(timeout)
}
if (shouldCallImmediate) {
initialValue = newValue
trigger()
shouldCallImmediate = false
return
}
timeout = setTimeout(() => {
initialValue = newValue
trigger()
shouldCallImmediate = immediate
}, delay)
}
}
})
}
使用场景
-
搜索框输入
用户停止输入后再触发搜索
-
窗口大小调整
防抖处理 resize 事件
-
表单验证
输入完成后才进行验证
-
实时保存
内容修改后延迟保存
-
API 请求
减少不必要的数据请求
// debounceRef.ts
import { customRef, type Ref } from 'vue'
/**
* 防抖自定义ref
* @param initialValue 初始值
* @param delay 延迟时间(毫秒),默认200ms
* @param immediate 是否立即执行,默认false
*/
export function useDebounceRef<T>(
initialValue: T,
delay = 200,
immediate = false
): Ref<T> {
let timeout: ReturnType<typeof setTimeout> | null = null
let shouldCallImmediate = immediate
return customRef<T>((track, trigger) => {
return {
get() {
track()
return initialValue
},
set(newValue: T) {
if (timeout) {
clearTimeout(timeout)
}
if (shouldCallImmediate) {
initialValue = newValue
trigger()
shouldCallImmediate = false
return
}
timeout = setTimeout(() => {
initialValue = newValue
trigger()
shouldCallImmediate = immediate
}, delay)
}
}
})
}
评论区