Vue3 customRef自定义ref 实现防抖

防抖就是防止在input 框中每输入一个字符就要向服务器请求一次,只要在用户输入完成过一段时间再读取用户输入的内容就能解决这个问题,减小服务器的压力。

**1.**自定义ref是一个函数,可以接受参数。

比如我们自定义一个myRef:

javascript 复制代码
setup() {
  let text = myRef("初始化");

  // 配置自定义的myRef
  function myRef(value) {}

  return { text };
},

**2.**在这个函数中,我们有一个返回值,这个返回值是customRef 函数。

在使用customRef 函数之前,我们需要先对其进行引入:

import { customRef } from "vue";

javascript 复制代码
setup() {
  let text = myRef("初始化");

  function myRef(value) {
    return customRef()
  }

  return { text };
},

**3.**customRef 函数的参数是一个函数。

该函数中又返回一个对象。

对象中有get函数和set函数。

javascript 复制代码
setup() {
  let text = myRef("初始化");

  function myRef(value) {
    return customRef(() => {
      return {
        get() { },
        set() { }
      }
    })
  }

  return { text };
},

**4.**当我们在模板中读取使用自定义ref 定义的数据时就会调用get 函数,修改数据时就会调用set 函数。原理和Proxy 对象中的get、set 差不多。

我们将get 函数中的返回值作为解析模板后数据的值。

而set 函数中,参数newValue为value修改后的值,我们需要将新的值赋值给传入的value值,才能实现页面的响应式。

javascript 复制代码
setup() {
  let text = myRef("初始化");

  function myRef(value) {
    return customRef(() => {
      return {
        // 读取value 调用get
        get() {
          return value;
        },
        // 修改value 调用set
        set(newValue) {
          value = newValue;
        }
      }
    })
  }

  return { text };
},

**5.**以上代码实现后,其实并没有真正实现响应式。至少说我们改变text数据,页面其他用到text的地方并没有改变。

原因就在于我们改变value值后触发get 函数后并没有去重新解析模板,set 也没有收到解析模板的命令。

因此customRef 函数中又有两个参数,track 函数和trigger 函数。

track函数用于通知vue追踪value的变化;trigger函数用于通知vue重新解析模板。

javascript 复制代码
setup() {
  let text = myRef("初始化");

  function myRef(value) {
    return customRef((track, trigger) => {
      return {
        get() {
          track();  // 通知vue追踪value的变化
          return value;
        },
        set(newValue) {
          value = newValue;
          trigger();  // 通知vue重新解析模板
        }
      }
    })
  }

  return { text };
},

**6.**最后我们加上定时器,就能实现防抖的效果。

javascript 复制代码
setup() {
  let text = myRef("初始化", 1000);

  function myRef(value, delay) {
    let timer;  // 定时器
    return customRef((track, trigger) => {
      return {
        get() {
          track();
          return value;
        },
        set(newValue) {
          // 如果定时器已经开启了,就清除当前定时器,新开一个定时器
          clearTimeout(timer);  
          timer = setTimeout(() => {
            value = newValue;
            trigger();
          }, delay);
        },
      };
    });
  }

  return { text };
},
相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60613 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅4 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax