vue3官网防抖ref?

以下是vue3官网的代码 “防抖ref”

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

为什么set的时候,定时器已经清除了,定时器里的内容还会执行呢?newValue的值还会一直在,并且累积到200ms后全部执行

阅读 1.9k
1 个回答

因为清除的是上一次调用set时生成的延时器。
clearTimeout并不介意接收一个已经执行过的延时器,所以clearTimeout(timeout)的实际效果等价于:

if(xxxxx){
  // 如果 timeout 对应的延时器有效,就清除该延时器
  clearTimeout(timeout)
} else {
  // 如果该延时器无效,就不用管
}
// 以上,timeout 指的是“上一次”的延时器
// 后面可以重新给 timeout 赋值,此后 timeout 就成了“这一次”的延时器
// 上面清除的是“上一次”的延时器,不会影响“这一次”的回调函数

那你可能会说,“下一次”执行set的时候岂不是就把“这一次”设置的timeout给清除掉了?
这就要看“下一次”是什么时候执行的:

  • 如果这个时候timeout还没有过期,那么确实就应该把它给清除掉,这就是“防抖”的含义——时间小于某个阈值的连续操作,需要取消前面一次操作;

    注意这里不存在“积累到200ms之后全部执行”的说法,而是上一次的newValue在清除的时候就直接取消了,面试的时候可不能那样理解。
  • 如果这个时候timeout已经过期了,那么清除不影响已经执行过的“上一次”的代码。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题