[Vue] computed について知ろう

Vue3では、従来のオプションAPIに加えて、Composition APIが導入されました。Composition APIでは、Vue2のcomputedプロパティに相当する機能を、computed関数として提供しています。computed関数は、状態の変化に応じて再評価されるリアクティブな値を作成することができます。

目次

computed関数の使い方

computed関数は、2つの引数を取ります。

  1. getter関数:計算されたプロパティの値を返す関数です。
  2. setter関数(オプション):計算されたプロパティの値が変更されたときに呼び出される関数です。変更を反映するための状態の更新をここで行います。

以下は、単純な例です。nameageという2つの状態を使って、fullNameという計算されたプロパティを作成します。

import { computed, reactive } from 'vue'

const state = reactive({
  name: 'John',
  age: 30
})

const fullName = computed(() => {
  return `${state.name} (${state.age})`
})

fullNameは、state.namestate.ageが変更されるたびに再評価されます。

Composition APIでのcomputedの使い方

Composition APIを使用すると、setup関数内でcomputed関数を使用することができます。以下は、Composition APIを使用した例です。

import { computed, reactive, toRefs } from 'vue'

export default {
  setup() {
    const state = reactive({
      name: 'John',
      age: 30
    })

    const fullName = computed(() => {
      return `${state.name} (${state.age})`
    })

    return {
      ...toRefs(state),
      fullName
    }
  }
}

toRefs関数を使用すると、stateオブジェクト内のプロパティがリアクティブな参照として公開されます。fullNameプロパティも同様に公開されます。これにより、テンプレート内でこれらの値に簡単にアクセスすることができます。

<template>
  <div>
    <p>Name: {{ name }}</p>
    <p>Age: {{ age }}</p>
    <p>Full name: {{ fullName }}</p>
  </div>
</template>

computedプロパティとcomputed関数の違い

従来のオプションAPIでは、Vueコンポーネントでcomputedプロパティを定義していました。Composition APIでは、代わりにcomputed関数を使用します。computed関数は、Vueコンポーネントのsetup関数内で呼び出されます。以下は、オプションAPIとComposition APIでのcomputedの使用例です。

オプションAPI

export default {
  data() {
    return {
      name: 'John',
      age: 30
    }
  },
  computed: {
    fullName() {
      return `${this.name} (${this.age})`
    }
  }
}

Composition API

import { computed, reactive, toRefs } from 'vue'

export default {
  setup() {
    const state = reactive({
      name: 'John',
      age: 30
    })

    const fullName = computed(() => {
      return `${state.name} (${state.age})`
    })

    return {
      ...toRefs(state),
      fullName
    }
  }
}

オプションAPIでは、computedプロパティは、コンポーネントのオプションオブジェクト内に定義されます。Composition APIでは、computed関数は、setup関数内で定義されます。

computed関数のリアクティブな依存関係

computed関数は、参照するデータに基づいて自動的に再評価されます。この依存関係は、Vueによってトラッキングされ、必要に応じて再評価されます。以下は、リアクティブな状態の変更に応じてcomputedプロパティが自動的に更新される例です。

import { computed, reactive } from 'vue'

const state = reactive({
  name: 'John',
  age: 30
})

const fullName = computed(() => {
  return `${state.name} (${state.age})`
})

console.log(fullName.value) // "John (30)"

state.age = 31

console.log(fullName.value) // "John (31)"

fullNameは、state.namestate.ageに依存しているため、state.ageが変更されると、自動的に再評価されます。

computed関数のキャッシュ

computed関数は、その結果をキャッシュし、同じ入力に対して複数回評価されないようにします。キャッシュされた値は、同じ参照が保持されるため、computed関数の返り値はrefオブジェクトではなく、その値自体です。以下は、computed関数のキャッシュの例です。

import { computed } from 'vue'

const count = ref(0)

const doubled = computed(() => {
  console.log('computed!')
  return count.value * 2
})

console.log(doubled.value) // 0
count.value = 1
console.log(doubled.value) // 2

computed関数は、最初に呼び出されたときにキャッシュされ、以降の呼び出しでは、キャッシュされた値が返されます。上記の例では、最初の呼び出しではcomputed!がコンソールにログされますが、2回目の呼び出しではログされません。

computed関数とwatch関数を組み合わせる

computed関数は、デフォルトではリアクティブな状態をすべて監視しますが、この振る舞いをカスタマイズすることもできます。computed関数には、オプションとして、監視するリアクティブな状態を明示的に指定することができるwatchオプションがあります。このオプションを指定することで、computed関数の再評価をトリガーするリアクティブな状態を明示的に制御できます。以下は、watchオプションを使用したcomputed関数の例です。

import { computed, reactive } from 'vue'

const state = reactive({
  name: 'John',
  age: 30
})

const fullName = computed(
  () => {
    console.log('computed!')
    return `${state.name} (${state.age})`
  },
  { watch: { age: true } }
)

console.log(fullName.value) // "John (30)"

state.name = 'Jane'

console.log(fullName.value) // "John (30)"

state.age = 31

console.log(fullName.value) // "Jane (31)"

上記の例では、watchオプションが{ age: true }に設定されており、fullNamestate.ageに依存しています。したがって、state.ageの値が変更されると、fullNameは再評価されますが、state.nameの値が変更されても再評価されません。

まとめ

computed関数は、VueのComposition APIで、リアクティブな値を計算するために使用されます。computed関数は、自動的に再評価され、キャッシュされ、メモ化することができます。watchオプションを使用することで、computed関数が再評価されるトリガーとなるリアクティブな状態を制御できます。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次