标准答案
- customRef 接收 track 和 trigger,读取值时调用 track 收集依赖,合适的时机调用 trigger 通知依赖更新。
- 防抖输入场景里,customRef 可以让 v-model 绑定的响应式值在停顿后才真正更新。
- watch 防抖通常是值已经变化了,只是把请求、校验、保存等副作用延迟执行。
- customRef 改变的是响应式值对外可见的更新时机,watch 防抖改变的是副作用执行时机。
- 如果只是防抖请求,优先用 watch 或事件处理防抖;如果需要把防抖能力封装成一个响应式值,再考虑 customRef。
题目解析
这道题的重点是区分“状态更新防抖”和“副作用防抖”。两者表现相似,但对表单、校验和 UI 反馈的影响不同。
customRef 更靠近响应式底层,封装后调用体验很好,但也更容易隐藏真实更新时间。
在复杂表单里,如果输入框显示、校验状态、接口请求都依赖同一字段,要明确哪些部分需要即时响应,哪些部分可以防抖。
代码示例
下面的 customRef 会在输入停止一段时间后再触发依赖更新。
TypeScript
function useDebouncedRef<T>(initialValue: T, delay = 300) {
let value = initialValue
let timer: ReturnType<typeof setTimeout> | undefined
return customRef<T>((track, trigger) => ({
get() {
track()
return value
},
set(nextValue) {
clearTimeout(timer)
timer = setTimeout(() => {
value = nextValue
trigger()
}, delay)
}
}))
}常见误区
- 把 customRef 和 watch 防抖说成完全一样,忽略一个控制值更新,一个控制副作用执行。
- 所有输入都用 customRef 防抖,导致输入框显示、校验和提交状态变得迟钝。
- 在 customRef 里忘记 track 或 trigger,导致依赖无法收集或视图不更新。