VueUse 源码解析之 resolveRef 和 resolveUnRef

461 阅读1分钟

VueUseresolverefresolveref 解析

TL;TD

resolveRef 和 resolveUnRef 两个通用的 ref 处理方法。

resolveRef

resolveRef 可以接受一个正常的 value 或者一个 ref 对象或者一个有返回值的回调函数作为参数,然后返回一个 ref 对象。

我们简单实现一个计数器,代码如下:

<script setup>
import { ref } from "vue";

const count = ref(0);

const calculate = (countStep) => {
	count.value += countStep;
}

const inc = (delta) => {
	calculate(+delta);
}

const dec = (delta) => {
	calculate(-delta);
}

</script>

<template>
	<h1>count: {{ count }}</h1>
	<button @click="inc(5)">+ 5</button>
	<button @click="dec(5)">- 5</button>
</template>

浏览器展示效果:

计数器

在上面代码的基础上,现在增加自定义步长计数:

<script setup>
import { ref } from "vue";

const count = ref(0);
const step = ref(1);

const calculate = (countStep) => {
	// 注意这里
	count.value += countStep;
}

const inc = (delta) => {
	calculate(+delta);
}

const dec = (delta) => {
	calculate(-delta);
}

const countStep = () => {
	calculate(step);
}

</script>

<template>
	step: <input type="number" v-model="step" />
	<h1>count: {{ count }}</h1>
	<button @click="inc(5)">+ 5</button>
	<button @click="dec(5)">- 5</button>
	<button @click="countStep">add step</button>
</template>

展示代码写完,逻辑代码遇到了麻烦,calculate 的参数 countStep 除了是正常值还可以是一个 ref 对象,我们用 ref API 进行处理:

count.value += ref(countStep).value;

完美解决。现在再新增 add two step 按钮:

<button @click="countTwoStep">add two step</button>

countTwoStep 函数采用回调的形式:

const countTwoStep = () => {
	calculate(() => step.value * 2);
}

不用我说,估计你也知道 calculate 需要增加一个判断然后结合 computed:

const calculate = (countStep) => {
	const v = typeof countStep === "function" ? computed(countStep): countStep;
	count.value += ref(v).value;
}

这个时候我们可以把判断逻辑抽象成 resolveRef:

const resolveRef = (r) => {
	return typeof r === "function" ? computed(r): ref(r);
}

const calculate = (countStep) => {
	count.value += resolveRef(countStep).value;
}

大功告成!

resolveUnRef

resolveUnRef 可以接受一个正常的 value 或者一个 ref 对象或者一个有返回值的回调函数作为参数,然后返回一个不是 ref 的正常值。

观察计算逻辑,使用 .value 就是没有直接使用数计算直观:

count.value += resolveRef(countStep).value;

还是使用 resolveUnRef 比较合适,根据 resolveRef 的思路,实现 resolveUnRef 实现如下:

const resolveUnRef = (r) => {
	return typeof r === "function" ? r(): unref(r);
}

const calculate = (countStep) => {
	count.value += resolveUnRef(countStep);
}