Vue3 customRef创建自定义响应式引用的防抖输入
在Vue3中处理表单输入时,为避免频繁触发搜索请求或页面重渲染,通常需要对输入事件进行防抖处理。使用customRef可以创建一个具备内置防抖功能的响应式引用,从而将防抖逻辑从业务组件中解耦,实现逻辑复用。
核心原理分析
customRef 允许开发者显式地控制依赖追踪(track)和响应触发(trigger)的时机。在防抖场景下,数据读取时立即追踪依赖,数据写入时并不立即触发更新,而是开启一个延时器,仅在规定时间内无新输入时才触发更新。
以下是防抖 Ref 的内部行为流程:
实施步骤
-
创建 工具函数文件(如
useDebouncedRef.js)。 -
导入 必要的 API。
在文件顶部 引入customRef。import { customRef } from 'vue' -
定义 防抖 Ref 函数。
编写 一个名为useDebouncedRef的函数,接收初始值value和延迟时间delay(默认设为 200毫秒)。export function useDebouncedRef(value, delay = 200) { let timeout return customRef((track, trigger) => { // 后续逻辑将在此处编写 }) } -
实现 数据读取逻辑。
在customRef的回调函数中 返回 一个对象,首先 实现get方法。在此方法中 调用track()告知 Vue 追踪该值的变化,并 返回 当前value。get() { track() return value }, -
实现 数据写入与防抖逻辑。
编写set方法。在此方法中先 清除 之前的定时器,防止频繁触发,随后 创建 新的定时器。当定时器结束,更新 内部值并 调用trigger()通知 Vue 重新渲染。set(newValue) { clearTimeout(timeout) timeout = setTimeout(() => { value = newValue trigger() }, delay) } -
整合 完整代码。
完整的工具函数代码如下:import { customRef } from 'vue' export function useDebouncedRef(value, delay = 200) { let timeout return customRef((track, trigger) => { return { get() { track() return value }, set(newValue) { clearTimeout(timeout) timeout = setTimeout(() => { value = newValue trigger() }, delay) } } }) }
组件中的应用
-
引入 防抖函数。
在 Vue 组件的<script setup>中 导入 刚才创建的useDebouncedRef。import { useDebouncedRef } from './useDebouncedRef' -
初始化 响应式数据。
使用该函数 声明 响应式变量,例如搜索关键词keyword,并 设置 延迟时间为 500毫秒。const keyword = useDebouncedRef('', 500) -
绑定 模板数据。
在模板中 使用v-model将输入框绑定到keyword。此时,输入框的输入事件会触发防抖逻辑,而keyword的值将在停止输入 500毫秒后更新。<template> <div> <input type="text" v-model="keyword" placeholder="请输入搜索内容" /> <p>当前搜索词: {{ keyword }}</p> </div> </template>
方案对比
使用 customRef 实现防抖与传统的 watch 或 lodash 防抖函数相比,具有明显的结构优势:
| 特性 | 传统 watch/debounce | customRef 防抖 |
|---|---|---|
| 逻辑位置 | 分散在组件的监听逻辑中 | 封装在 Ref 定义处 |
| 复用性 | 需在每个组件重复编写监听代码 | 直接调用函数即可 |
| 绑定方式 | 需绑定原生事件或监听值变化 | 直接支持 v-model |
| 响应控制 | 由 Vue 自动触发,需手动拦截 | 完全手动控制触发时机 |
通过这种方式,响应式数据本身具备了“防抖”特性,业务代码中无需再关注防抖细节,极大简化了组件逻辑。

暂无评论,快来抢沙发吧!