侧边栏壁纸
  • 累计撰写 47 篇文章
  • 累计创建 2 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Vue:自定义Ref,实现防抖功能

实现
// 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)
      }
    }
  })
}
使用场景
  1. 搜索框输入

    用户停止输入后再触发搜索

  2. 窗口大小调整

    防抖处理 resize 事件

  3. 表单验证

    输入完成后才进行验证

  4. 实时保存

    内容修改后延迟保存

  5. 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)
      }
    }
  })
}
0

评论区