2. VueUse 最佳实践
2. VueUse 最佳实践
Vue3 Ref 对象
在下文及后续文档中,Ref
对象指的是由 ref()
创建的响应式对象,也可以写作 ref,ref 的类型是 Ref
。当宽泛地指代可能不止一个 Ref
对象时,使用 refs。
1. 解构
VueUse 中的大多数函数都会返回一个 Ref
对象,你可以使用 ES6 的对象解构语法来获取你需要的东西,例如:
import { useMouse } from '@vueuse/core'
// "x" 和 "y" 都是 refs
const { x, y } = useMouse()
console.log(x.value)
const mouse = useMouse()
console.log(mouse.x.value)
如果你喜欢把它们作为对象属性的样式来使用,你可以通过使用 reactive()
来解除对 refs 的包装,例如:
import { reactive } from 'vue'
import { useMouse } from '@vueuse/core'
const mouse = reactive(useMouse())
// "x" 和 "y" 将自动解包装,不需要 `.value`
console.log(mouse.x)
2. 清除副作用
类似于 Vue 的 watch
和 computed
在组件被卸载时将被处置,VueUse 的函数也会自动清理副作用。
例如,useEventListener
会在组件卸载时调用 removeEventListener
,所以你不需要担心这个问题。
// 将会自动清理
useEventListener('mousemove', () => {})
所有 VueUse 函数都遵循这个惯例。
为了手动处理副作用,一些函数像 watch
函数一样返回一个停止处理程序。例如:
const stop = useEventListener('mousemove', () => {})
// 手动解除事件监听器
stop()
虽然不是所有的函数都会返回处理程序,但一个更通用的解决方案是使用 Vue 的 effectScope
API。
import { effectScope } from 'vue'
const scope = effectScope()
scope.run(() => {
// ...
useEventListener('mousemove', () => {})
onClickOutside(el, () => {})
watch(source, () => {})
})
// 所有在 `scope.run` 中调用的组合函数将自动解除
scope.stop()
了解更多关于作用范围的描述,阅读 Vue RFC: Reactivity Effect 了解更多。
3. 将 ref 作为参数传递
在 Vue 中,我们使用 setup()
函数来构建数据和逻辑之间的连接。为了使其灵活,大部分 VueUse 函数也接受参数的 ref 版本。
下面以 useTitle
为例,展示各种 ref 传参用法。
3.1 常规用法
通常,useTitle
返回一个页面标题的引用。当你给这个引用分配新的值时,它会自动更新标题。
const isDark = useDark()
const title = useTitle('Set title')
watch(isDark, () => {
title.value = isDark.value ? '🌙 Good evening!' : '☀️ Good morning!'
})
3.2 连接使用
如果用 “连接” 的思想来写,你可以传递一个 ref,使其与页面的标题绑定。
const isDark = useDark()
const title = computed(() => isDark.value ? '🌙 Good evening!' : '☀️ Good morning!')
useTitle(title)
3.3 响应式 Getter
从 VueUse 9.0 开始,我们引入了一个新的约定,将响应式 Getter 作为参数传递。这在处理响应式对象和 Reactivity Transform 中非常有效。
const isDark = useDark()
useTitle(() => isDark.value ? '🌙 Good evening!' : '☀️ Good morning!')