lengxing/MyBlog

Vue3 Composable最佳实践(二)

lengxing opened this issue · 0 comments

pt2rev.jpeg

本文为翻译文章,部分内容难免理解有偏差,如有错误欢迎大家指正。原文链接见文章末尾。

在使用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的时候,页面的标题将会被设置成这个refvalue

const title = ref('这里是标题'); 
useTitle(title); 
title.value = '这是一个新标题';

如果我们传入一个字符串变量的话,它将会创建一个新的ref和标题进行关联:

const title = useTitle('这里是标题'); 
title.value = '这是一个新标题';

上面的例子可能看起来区别不大,但是,在我们使用到一些方法或者组合式API的时候,我们可能会有不同的引用来源,从而这个组合式可以适应不同的情况。下面让我们来看一下如何在我们的组合式中使用这种模式。

在组合式中实现灵活的参数

想实现灵活的参数模式,我们需要使用到refunref方法在参数上面。

// 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(空值合并)运算符,其语法为“??”,意思是“如果左侧的值为nullundefined,则使用右侧的值”。在代码中,如果newTitle未定义,则使用document.title,如果document.title也未定义,则使用null。这个运算符可以用于简化代码中的条件判断。

另外,useTitle的类型定义中还使用到了TypeScript 中的 MaybeRef 类型,它可以是 string 类型或 Ref<string> 类型。其中 Ref<T> 是一个带有 T 类型值的 ref

type MaybeRef<T> = T | Ref<T>

举例-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)的第二个模式。该模式使用refunref函数来更灵活地使用参数,使可组合函数能够适应不同的使用情况。还介绍了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 });

原文链接: # Coding Better Composables (2/5)