文章目录

Vue3 customRef创建自定义响应式引用的防抖输入

发布于 2026-05-13 18:10:17 · 浏览 12 次 · 评论 0 条

Vue3 customRef创建自定义响应式引用的防抖输入

在Vue3中处理表单输入时,为避免频繁触发搜索请求或页面重渲染,通常需要对输入事件进行防抖处理。使用customRef可以创建一个具备内置防抖功能的响应式引用,从而将防抖逻辑从业务组件中解耦,实现逻辑复用。


核心原理分析

customRef 允许开发者显式地控制依赖追踪(track)和响应触发(trigger)的时机。在防抖场景下,数据读取时立即追踪依赖,数据写入时并不立即触发更新,而是开启一个延时器,仅在规定时间内无新输入时才触发更新。

以下是防抖 Ref 的内部行为流程:

graph TD A["用户输入"] --> B["set(newValue)"] B --> C["clearTimeout"] C --> D["setTimeout"] D --> E{"延迟时间到?"} E -- "是" --> F["value = newValue"] F --> G["trigger()"] G --> H["视图更新"] I["组件读取"] --> J["get()"] J --> K["track()"]

实施步骤

  1. 创建 工具函数文件(如 useDebouncedRef.js)。

  2. 导入 必要的 API。
    在文件顶部 引入 customRef

    import { customRef } from 'vue'
  3. 定义 防抖 Ref 函数。
    编写 一个名为 useDebouncedRef 的函数,接收初始值 value 和延迟时间 delay(默认设为 200毫秒)。

    export function useDebouncedRef(value, delay = 200) {
      let timeout
      return customRef((track, trigger) => {
        // 后续逻辑将在此处编写
      })
    }
  4. 实现 数据读取逻辑。
    customRef 的回调函数中 返回 一个对象,首先 实现 get 方法。在此方法中 调用 track() 告知 Vue 追踪该值的变化,并 返回 当前 value

    get() {
      track()
      return value
    },
  5. 实现 数据写入与防抖逻辑。
    编写 set 方法。在此方法中先 清除 之前的定时器,防止频繁触发,随后 创建 新的定时器。当定时器结束,更新 内部值并 调用 trigger() 通知 Vue 重新渲染。

    set(newValue) {
      clearTimeout(timeout)
      timeout = setTimeout(() => {
        value = newValue
        trigger()
      }, delay)
    }
  6. 整合 完整代码。
    完整的工具函数代码如下:

    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)
          }
        }
      })
    }

组件中的应用

  1. 引入 防抖函数。
    在 Vue 组件的 <script setup>导入 刚才创建的 useDebouncedRef

    import { useDebouncedRef } from './useDebouncedRef'
  2. 初始化 响应式数据。
    使用该函数 声明 响应式变量,例如搜索关键词 keyword,并 设置 延迟时间为 500毫秒。

    const keyword = useDebouncedRef('', 500)
  3. 绑定 模板数据。
    在模板中 使用 v-model 将输入框绑定到 keyword。此时,输入框的输入事件会触发防抖逻辑,而 keyword 的值将在停止输入 500毫秒后更新。

    <template>
      <div>
        <input type="text" v-model="keyword" placeholder="请输入搜索内容" />
        <p>当前搜索词: {{ keyword }}</p>
      </div>
    </template>

方案对比

使用 customRef 实现防抖与传统的 watchlodash 防抖函数相比,具有明显的结构优势:

特性 传统 watch/debounce customRef 防抖
逻辑位置 分散在组件的监听逻辑中 封装在 Ref 定义处
复用性 需在每个组件重复编写监听代码 直接调用函数即可
绑定方式 需绑定原生事件或监听值变化 直接支持 v-model
响应控制 由 Vue 自动触发,需手动拦截 完全手动控制触发时机

通过这种方式,响应式数据本身具备了“防抖”特性,业务代码中无需再关注防抖细节,极大简化了组件逻辑。

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文