直接用customref封装防抖ref可使v-model自动具备防抖能力,核心是get时调用track()、set延迟更新后调用trigger(),定时器需闭包隔离,支持cancel/flush方法且组件卸载时清理。

直接用 customRef 封装一个防抖 ref,就能让 v-model 自动具备防抖能力,不需要额外监听事件或写 watch。
核心要点:track 和 trigger 必须成对出现
customRef 不像普通 ref 那样自动处理依赖追踪。它把控制权完全交给你:
-
每次 get 时必须调用
track()—— 告诉 Vue “这个值正在被读取”,否则模板首次渲染后就不再响应变化 -
每次真正更新值后必须调用
trigger()—— 告诉 Vue “值已稳定,该刷新视图了”,否则即使内部变量变了,界面也不更新 - 定时器变量(如
timer)要定义在闭包里,确保每个 ref 实例互不干扰
封装一个可复用的 debounceRef
下面是一个带取消和立即提交能力的健壮版本:
import { customRef } from 'vue'
export function debounceRef(value, delay = 300) {
let timer = null
return customRef((track, trigger) => ({
get() {
track()
return value
},
set(newValue) {
clearTimeout(timer)
timer = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}))
}
使用时就像普通 ref 一样:
const searchQuery = debounceRef('', 500)
// 模板中直接绑定
<input v-model="searchQuery"><div>当前值:{{ searchQuery }}</div>
支持 cancel 和 flush 的增强版
实际项目中常需要手动干预防抖行为,比如清空输入时立刻提交空值:
export function useDebouncedRef(value, delay = 300) {
let timer = null
const ref = customRef((track, trigger) => ({
get() {
track()
return value
},
set(newValue) {
clearTimeout(timer)
timer = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}))
// 暴露控制方法
ref.cancel = () => clearTimeout(timer)
ref.flush = () => {
clearTimeout(timer)
trigger() // 强制通知当前值已生效
}
return ref
}
组件内可这样调用:
const query = useDebouncedRef('', 400)
// 清空输入框时立即提交空值
const clear = () => {
query.value = ''
query.flush()
}
为什么比 watch + setTimeout 更干净?
用 watch(searchQuery, ...) 方式做防抖,中间几十次输入仍会触发 watch 回调;而 customRef 把响应式更新“卡”在防抖结束那一刻,中间赋值完全不触发任何副作用——计算属性不重算、接口不发起、模板不重渲染。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











