一个强大的 Vue3 API,让你随心所欲操控数据更新!

文摘   2024-11-15 10:11   山西  

今天我们聊点技术活,专门给前端的小伙伴们解解渴。最近在处理 Vue3 项目中的一个需求时,遇到了一个特别有用的 API——customRef

在我们的日常开发中,很多时候都会面临数据更新的困境,比如当我们有一个 computed 计算属性,它依赖于多个变量,但有些变量是非响应式的,那么这些非响应式变量发生变化时就不会触发 computed 的重新计算。

这时候该怎么办呢?别急,Vue3 给我们提供了一个强大的工具,帮助我们随心所欲地控制数据更新,这就是 customRef。

简单来说,我们有一个 computed 计算属性 sum,它依赖于一些响应式变量,也依赖于一些非响应式变量。

在 Vue 中,当响应式变量发生变化时,computed 会自动更新,但是如果是非响应式变量发生变化,computed 就不会触发更新。

举个例子,如果 sum 的计算依赖了变量 count1count2,而 count1 是响应式的,count2 是普通变量,那么当 count2 改变时,sum 并不会更新。为了解决这个问题,我们可以使用 Vue3 的 customRef

customRef 是 Vue3 提供的一个强大的 API,它允许我们创建一个自定义的 ref,从而显式地声明对其依赖追踪和更新触发的控制方式。简单来说,customRef 给了我们更多的控制权,让我们能精确地控制数据的更新时机。

customRef() 接受一个工厂函数,这个函数有两个参数:tracktrigger。这两个函数分别用来追踪依赖和触发更新。track() 通常在 get() 方法中调用,trigger() 则在 set() 中调用。通过这种方式,我们可以精确地控制什么时候进行依赖追踪,什么时候触发更新。

创建一个防抖 ref

我们可以通过 customRef 实现一些自定义的行为,比如创建一个防抖的 ref,即只有在 set 被调用后一段固定时间后才触发更新。这种用法在一些高频更新的场景中非常有用,比如搜索框输入时防止每次输入都触发请求。

import { customRef } from 'vue';

function useDebouncedRef(initialValue, delay{
  let timeout;
  return customRef((track, trigger) => {
    return {
      get() {
        track(); // 追踪依赖
        return initialValue;
      },
      set(value) {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
          initialValue = value;
          trigger(); // 延迟触发更新
        }, delay);
      }
    };
  });
}

在这个例子中,useDebouncedRef 创建了一个防抖的 ref。当我们为 ref 设置一个新值时,set() 方法会清除之前的定时器,并设置一个新的定时器来在指定的 delay 后更新 ref 的值。这样就能有效地防止频繁触发更新。

可控的 computed

回到我们刚才的需求,我们需要一个“可控的 computed”。这意味着我们希望能够手动触发 computed 的更新,特别是在一些非响应式变量变化时,computed 的值也能重新计算。

为了实现这一点,我们依然可以使用 customRef 来创建一个带有自定义更新逻辑的 computed

假设我们有如下的需求:sum 依赖于 count1(响应式)和 count2(非响应式),当 count2 变化时,我们希望 sum 能够手动触发更新。我们可以这样实现:

import { reactive, computed, customRef } from 'vue';

function useManualComputed(deps, computeFn{
  let value;
  let dirty = true;

  const ref = customRef((track, trigger) => {
    return {
      get() {
        if (dirty) {
          track();  // 追踪依赖
          value = computeFn();
          dirty = false;
        }
        return value;
      },
      set() {
        dirty = true// 手动设置为脏数据,强制重新计算
        trigger();
      }
    };
  });

  // 返回 ref 和手动更新的方法
  return [ref, () => { dirty = true; }];
}

// 使用方式
const count1 = reactive({ value0 });
let count2 = 10;

const sumFn = () => count1.value + count2;

const [sum, refreshSum] = useManualComputed([count1, count2], sumFn);

console.log(sum.value); // 0

// 修改 count2,不会自动触发 sum 的更新
count2 = 20;
refreshSum(); // 手动触发更新

console.log(sum.value); // 20

在这个例子中,useManualComputed 返回一个包含 computed 值的 ref 和一个手动触发更新的函数 refreshSum。当 count2 改变时,我们可以调用 refreshSum 来手动触发 sum 的更新。

customRef 这个 API 在 Vue3 中为我们提供了更多的控制权,尤其是在面对复杂的数据更新逻辑时。通过 customRef,我们可以创建带有自定义行为的响应式数据,不仅能够精确控制依赖追踪,还能灵活地触发更新。

如果你在项目中遇到了类似的需求,比如需要在非响应式变量变化时手动触发 computed 更新,customRef 绝对是一个值得一试的好工具。

通过它,我们不仅能解决这些问题,还能在很多场景中实现更高效的数据更新机制。希望这篇文章能帮助到大家,让你们在开发中更加得心应手。

目前,对编程、职场感兴趣的同学,大家可以联系我微信:golang404,拉你进入“程序员交流群”。

虎哥私藏精品 热门推荐

虎哥作为一名老码农,整理了全网最前端资料合集

资料包含了《前端面试题PDF合集》、《前端学习视频》、《前端项目及源码》,总量高达108GB。

全部免费领取全面满足各个阶段程序员的学习需求!

web前端专栏
回复 javascript,获取前端面试题。分享前端教程,AI编程,AI工具,Tailwind CSS,Tailwind组件,javascript教程,webstorm教程,html教程,css教程,nodejs教程,vue教程。
 最新文章