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 };
},
相关推荐
Mintopia6 分钟前
⚙️ Next.js 缓存与队列:当数据与请求跳起“低延迟之舞”
前端·全栈·next.js
Shi_haoliu14 分钟前
Vue2 + Office Add-in关于用vue项目于加载项控制excel单元格内容(Demo版)
前端·javascript·vue.js·node.js·html·excel·office
计算机毕业设计木哥38 分钟前
计算机毕业设计选题推荐:基于SpringBoot和Vue的爱心公益网站
java·开发语言·vue.js·spring boot·后端·课程设计
IT_陈寒1 小时前
Redis 性能翻倍的 5 个隐藏技巧,99% 的开发者都不知道第3点!
前端·人工智能·后端
街尾杂货店&1 小时前
css word属性
前端·css
fruge3 小时前
2025前端工程化与性能优化实战指南:从构建到监控的全链路方案
前端·性能优化
aesthetician4 小时前
Node.js v25 重磅发布!革新与飞跃:深入探索 JavaScript 运行时的未来
javascript·node.js·vim
知识分享小能手7 小时前
uni-app 入门学习教程,从入门到精通,uni-app基础扩展 —— 详细知识点与案例(3)
vue.js·学习·ui·微信小程序·小程序·uni-app·编程
demi_meng8 小时前
reactNative 遇到的问题记录
javascript·react native·react.js
MC丶科8 小时前
【SpringBoot 快速上手实战系列】5 分钟用 Spring Boot 搭建一个用户管理系统(含前后端分离)!新手也能一次跑通!
java·vue.js·spring boot·后端