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 };
},
相关推荐
wuk9981 小时前
实现ROS系统的Websocket传输,向Web应用推送sensor_msgs::Image数据
前端·websocket·网络协议
合作小小程序员小小店3 小时前
web网页开发,在线%考试管理%系统,基于Idea,vscode,html,css,vue,java,maven,springboot,mysql
java·前端·系统架构·vue·intellij-idea·springboot
天天进步20153 小时前
CSS Grid与Flexbox:2025年响应式布局终极指南
前端·css
Boop_wu4 小时前
[Java EE] 计算机基础
java·服务器·前端
Novlan14 小时前
TDesign UniApp 组件库来了
前端
用户47949283569154 小时前
React DevTools 组件名乱码?揭秘从开发到生产的代码变形记
前端·react.js
顾安r5 小时前
11.8 脚本网页 打砖块max
服务器·前端·html·css3
倚栏听风雨5 小时前
typescript 方法前面加* 是什么意思
前端
狮子不白5 小时前
C#WEB 防重复提交控制
开发语言·前端·程序人生·c#