Lzh on GitHub

最佳实践

最佳实践

解构

VueUse 中的大多数函数都返回一个 ref 对象,你可以使用 ES6 的对象解构 语法来获取你需要的部分。例如:

import { useMouse } from '@vueuse/core'

// "x" 和 "y" 都是 ref
const { x, y } = useMouse()
console.log(x.value)

const mouse = useMouse()
console.log(mouse.x.value)

如果你更喜欢将它们作为对象属性使用,你可以使用 reactive() 解开 ref。例如:

import { useMouse } from '@vueuse/core'
import { reactive } from 'vue'

const mouse = reactive(useMouse())
// "x" 和 "y" 会自动解开,无需 `.value`
console.log(mouse.x)

副作用清理

类似于 Vue 的 watchcomputed 在组件卸载时会自动销毁,VueUse 的函数也会自动清理副作用。

例如,useEventListener 会在组件卸载时调用 removeEventListener

// 会自动清理
useEventListener('mousemove', () => {})

所有 VueUse 函数都遵循这个约定。

要手动销毁副作用,一些函数会像 watch 函数一样返回一个停止处理程序。例如:

const stop = useEventListener('mousemove', () => {})

// ...

// 手动注销事件监听器
stop()

不是所有函数都返回 stop 处理程序,所以一个更通用的解决方案是使用 Vue 的 effectScope API

import { effectScope } from 'vue'

const scope = effectScope()

scope.run(() => {
  // ...
  
  useEventListener('mousemove', () => {})
  onClickOutside(el, () => {})
  watch(source, () => {})
})

// `scope.run` 中调用的所有可组合函数都将被销毁
scope.stop()

你可以在 这个 RFC 中了解更多关于 effectScope 的信息。

响应式参数

在 Vue 中,我们使用 setup() 函数来构建数据和逻辑之间的 “连接”。为了使其灵活,大多数 VueUse 函数也接受 ref 作为参数,因为 ref 是响应式的。

useTitle 为例:

非响应式参数

useTitle 可组合函数帮助你获取和设置当前页面的 document.title 属性。

const isDark = useDark()
const title = useTitle('Hello')

console.log(document.title) // "Hello"

watch(isDark, () => {
  title.value = isDark.value ? '🌙 Good evening!' : '☀️ Good morning!'
})

Ref 参数

你可以将一个 ref 传递给 useTitle,而不是使用返回的 ref

const isDark = useDark()
const title = computed(() => isDark.value ? '🌙 Good evening!' : '☀️ Good morning!')

useTitle(title)

响应式 Getter 参数

自 VueUse 9.0 起,我们引入了一种新的约定来传递 “响应式 Getter” 作为参数,它与响应式对象和 Reactivity Transform 配合得很好。

const isDark = useDark()
useTitle(() => isDark.value ? '🌙 Good evening!' : '☀️ Good morning!')