リアクティビティー パート2

リアクティビティー パート1で、データの変更を監視して、変更時に更新を自動的にトリガーする 優れたリアクティビティシステムrefについて学習しました。 ここでは、computedについて学習しましょう。

computed の基本

Vue には 算出プロパティ (computed) という仕組みがあります。 computed は、依存するデータの値から自動的に導出されるリアクティブなプロパティです。 依存するリアクティブデータの値が変わらない限り結果がキャッシュされ、無駄な再計算を防ぐのでパフォーマンス良く利用することができます。

<script setup>
import { computed, ref } from 'vue'

const score = ref(65)
const grade = computed(() => score.value >= 80 ? 'A' : 'B')
const color = computed(() => grade.value === 'A' ? '#ff0000' : 'inherit')
</script>

<template>
  <p :style="{ color }">
    成績:{{ grade }}
  </p>
</template>

score が変わると自動で grade が再計算されます。 逆に score が変わらない限り、何度使っても前回の計算結果を使います。

変数 color に注目してください。依存データに computed を利用することもできます。 grade が変わると、 <p> 要素のstyle属性 color プロパティ値がリアクティブに変更されます。

値は ref と同じく .value を通してアクセスすることができます。 ただし <template> 内では自動的に .value がアンラップされるため、 {{ grade }} と書くだけでOKです。

computed の仕組み

computed の本質は getter 関数 です。 依存するリアクティブデータを監視し、変更があったときだけ処理を実行します。 以下のような流れです:

  1. 初回アクセス時に計算
  2. 依存している値が変わるまで結果をキャッシュ
  3. 依存値が変わると再計算

これは、 通常の関数呼び出し(methods) とは大きく異なります。 methods は呼ばれるたびに処理されますが、 computed はキャッシュされます。

よくある使い方

  • フォーマット変換(例:日付や通貨の整形)
  • 条件によるラベル表示(合格/不合格 など)
  • 配列やリストのフィルタリング・ソート
  • 数値や文字列の結合・集計

書き込み可能な算出関数

computed は、デフォルトでは getter 関数のみです。 getterのみの computed に新しい値を代入しようとすると、ランタイム警告が表示されます。

<script setup>
import { computed, ref } from 'vue'

const count = ref(2)
const doubled = computed(() => count.value * 2)
</script>

<template>
  <!-- ランタイムエラーとなってしまう -->
  <input v-model="doubled" type="number">
  <p>count: {{ count }}</p>
</template>

computedgetter だけでなく setter も定義できます。 これにより、算出値を書き換えたときに元のデータに反映できます。

<script setup>
import { computed, ref } from 'vue'

const count = ref(2)
const doubled = computed({
  get: () => count.value * 2,
  set: (val) => {
    count.value = val / 2
  }
})
</script>

<template>
  <input v-model="doubled" type="number">
  <p>count: {{ count }}</p>
</template>

この場合、doubled を変更すると自動的に count も変わります。

現在の実装の課題

前回の学習では、「未完了のみ表示」チェックボックスを実装し、showUnDoneOnly と値が同期されるようにしました。 ですが、「未完了のみ表示」チェックボックスにチェックを入れても、未完了タスクで絞り込みがされていません。

チャレンジ

computed を使って、以下のリアクティブな値を、 filteredTodos という命名で実装してみましょう。

  • 「未完了のみ表示」がチェック状態の時は、 donefalse の Todo のみを表示
  • 「未完了のみ表示」のチェックが外れている時は、 すべての Todo を表示

次の手順に沿って実装してみましょう。

  1. <script setup> の中で、 filteredTodos という算出プロパティ( computed )を定義しましょう。
  2. filteredTodos の実装をしましょう。showUnDoneOnly の値によって、 todos の絞り込みをします。
  • showUnDoneOnlytrue の場合は、 done: false のTodoのみを返します
  • showUnDoneOnlyfalse の場合は、すべてのTodoを返します
  1. TodoList コンポーネントに :todos="todos" で、全てのリストを渡していましたが、 1,2 で実装した filteredTodosTodoList コンポーネントの todos propsに渡してみましょう。

もし行き詰まったら、以下のボタンをクリックして解答を見ることができます。

フォーム入力バインディング
Vueでは v-model ディレクティブを使うことで、フォーム要素やコンポーネントと「双方向データバインディング」を簡潔に実現できます。ユーザーの入力とVueのデータが常に同期され、フォーム制御が直感的になります。 ここでは、フォーム要素の v-model の利用方法について学習します。 ※コンポーネントの v-model は、コンポーネントの v-modelで学習します。
コンポーネントの v-model
フォーム入力バインディングで紹介したように、 v-model はフォーム入力欄とVueのデータを自動で同期してくれる仕組みです。 この v-model は、コンポーネントでも同じように使うことができます。
ファイル
エディタ
WebContainerを初期化中
ファイルをマウント中
依存関係をインストール中
Nuxtサーバーを起動中
Nuxtが準備完了を待機中
ターミナル