Nuxtモジュール : VueUse

Best Practice

ベストプラクティス

デストラクチャリング

VueUseのほとんどの関数は、必要なものを取り出すためにES6のオブジェクトデストラクチャリング構文を使用できるrefのオブジェクトを返します。例えば:

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を呼び出します。

import { useEventListener } from '@vueuse/core'
// ---cut---
// 自動的にクリーンアップされます
useEventListener('mousemove', () => {})

すべてのVueUse関数はこの規約に従います。

副作用を手動で破棄するために、一部の関数はwatch関数のようにストップハンドラーを返します。例えば:

import { useEventListener } from '@vueuse/core'
// ---cut---
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()

effectScopeについてはこのRFCで詳しく学ぶことができます。

リアクティブな引数

Vueでは、setup()関数を使用してデータとロジックの「接続」を構築します。柔軟性を持たせるために、ほとんどのVueUse関数は引数としてrefを受け入れます。refはリアクティブだからです。

useTitleを例にとります:

非リアクティブな引数

useTitleコンポーザブルは、現在のページのdocument.titleプロパティを取得および設定するのに役立ちます。

// @lib: dom
import { useDark, useTitle } from '@vueuse/core'
import { watch } from 'vue'
// ---cut---
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を渡すことができます。

import { useDark, useTitle } from '@vueuse/core'
import { computed } from 'vue'
// ---cut---
const isDark = useDark()
const title = computed(() => isDark.value ? '🌙 Good evening!' : '☀️ Good morning!')

useTitle(title)
リアクティブゲッター引数

VueUse 9.0以降、引数として「リアクティブゲッター」を渡す新しい規約を導入しました。これはリアクティブオブジェクトやReactivity Transformと非常に相性が良いです。

import { useDark, useTitle } from '@vueuse/core'
// ---cut---
const isDark = useDark()

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