本文为翻译文章,部分内容难免理解有偏差,如有错误欢迎大家指正。原文链接见文章末尾。
在使用Vue.js中的组合式时,有时你已经有了一个想要使用的ref
,而有时你没有。本文将介绍一种模式,让你可以以两种方式使用组合式,从而在编写应用程序时提供更多的灵活性。
本篇是这个系列文章的第二篇,全部涵盖内容如下:
- 1.如何通过选项对象参数使您的组合更加可配置;
- 2.使用ref和unref使我们的参数更加灵活; 本篇主题
- 3.如何使你的返回值更有用;
- 4.为什么从接口定义开始可以使你的组合式函数更强大;
- 5.如何使用异步代码而无需“等待” - 使您的代码更易于理解;
使用ref和unref来实现更灵活的参数传递
通常,组合式API需要某些类型的参数作为输入,通常会使用到响应式变量参数。它也可以是原始的Javascript类型,如字符串,数字或对象。但是,为了使组合式更具灵活性和可重用性,我们会希望它可以接受任意类型的参数,并在运行时将其转换为所需的类型。
// Works if we give it a ref we already have
const countRef = ref(2);
useCount(countRef);
// Also works if we give it just a number
const countRef = useCount(2);
我们上篇里面提到的useTitle
也适用于这种模式。当我们传入一个ref
的时候,页面的标题将会被设置成这个ref
的value
。
const title = ref('这里是标题');
useTitle(title);
title.value = '这是一个新标题';
如果我们传入一个字符串变量的话,它将会创建一个新的ref和标题进行关联:
const title = useTitle('这里是标题');
title.value = '这是一个新标题';
上面的例子可能看起来区别不大,但是,在我们使用到一些方法或者组合式API的时候,我们可能会有不同的引用来源,从而这个组合式可以适应不同的情况。下面让我们来看一下如何在我们的组合式中使用这种模式。
在组合式中实现灵活的参数
想实现灵活的参数模式,我们需要使用到ref
和unref
方法在参数上面。
// When we need to use a ref in the composable
export default useMyComposable(input) {
const ref = ref(input);
}
// When we need to use a raw value in the composable
export default useMyComposable(input) {
const rawValue = unref(input);
}
如果是非响应式的参数变量的话,ref
方法会创建一个新的ref
变量给我们;如果是响应式的话,它会直接将对应的变量返回给我们。
// Create a new ref
const myRef = ref(0);
// Get the same ref back
assert(myRef === ref(myRef));
unref
方法类似,只不过它是将变量的真实值返回给我们
// Unwrap to get the inner value
const value = unref(myRef);
// Returns the same primitive value
assert(value === unref(value));
下面让我们看看在VueUse
中使用这种模式的例子。
举例-useTitle
让我们继续来看下我们已经熟悉的useTitle
方法。它允许我们传入一个字符串或者是响应式字符串变量:
// 传入字符串变量
const titleRef = useTitle('Initial title');
// 传入响应式字符串变量
const titleRef = ref('Initial title');
useTitle(titleRef);
在它的源码中,我们可以看出,它通过ref
方法来处理我们传入的变量
// ...
const title = ref(newTitle ?? document?.title ?? null)
// ...
它使用到了JavaScript中的nullish coalescing(空值合并)运算符
,其语法为“??”,意思是“如果左侧的值为null
或undefined
,则使用右侧的值”。在代码中,如果newTitle
未定义,则使用document.title
,如果document.title
也未定义,则使用null
。这个运算符可以用于简化代码中的条件判断。
另外,useTitle
的类型定义中还使用到了TypeScript 中的 MaybeRef 类型,它可以是 string
类型或 Ref
类型。其中 Ref
是一个带有 T
类型值的 ref
。
type MaybeRef = T | Ref
举例-useCssVar
useCssVar
允许我们获取到CSS变量的值并在应用程序中使用它。和useTitle
不同的是,我们需要传入一个string类型的值,来查询对应DOM上面的CSS变量。通过unref
方法,来处理传入的变量 - string
类型或者是一个ref
:
// Using a string
const backgroundColor = useCssVar('--background-color');
// Using a ref
const cssVarRef = ref('--background-color');
const backgroundColor = useCssVar(cssVarRef);
通过查看它的源码,我们可以看出它使用了unRef
方法来处理传入的参数。而且,它还使用了一个辅助函数unrefElement
,用于确保获取的是 DOM
元素而不是 Vue
实例。
在VueUse
中很多组合式方法都使用了这个模式,如果你想深入研究的话,选择一个感兴趣的去看它的源码吧。
小结
本篇我们主要介绍了Vue.js中的可组合函数(composables)的第二个模式。该模式使用ref
和unref
函数来更灵活地使用参数,使可组合函数能够适应不同的使用情况。还介绍了VueUse库如何实现这种模式,并举例说明了useTitle和useCssVar可组合函数如何使用ref和unref函数。
下一篇中,我们将会介绍另一种模式,该模式可以根据需要返回单个值或对象,从而使可组合函数更易于使用。该模式可以使可组合函数更简单易用,尤其是在大多数情况下只需要单个值的情况下。
// Returns a single value
const isDark = useDark();
// Returns an object of values
const {
counter,
pause,
resume,
} = useInterval(1000, { controls: true });