0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vue3のデータはどこからどこへ行く?ゲームの持ち物検索画面で整理する

0
Last updated at Posted at 2026-08-01

Vue3でrefreactivecomputedwatchv-bindv-ifv-showv-forを学んできましたが、言葉だけを追うと役割が重なって見えました。
今回はゲームの持ち物検索画面を例に、<script setup>で作ったデータが、<template>のどこへ反映されるかを中心に整理してみます。

持ち物を検索して一覧を絞り込むだけの小さな画面にすると、元データ・検索語・表示用データ・画面表示のつながりを追いやすそうです。

まだ途中段階なので、勘違いなどあれば教えていただけるとうれしいです。

今日やったこと

Vue3の要素を「何の機能か」ではなく、「どこで値を持ち、どこへ反映するか」で見直しました。

Vueのテンプレートは、コンポーネント内のデータとブラウザに描画されるDOMを結び付けるHTMLベースの構文です。リアクティブな値をテンプレートで参照すると、値の変更に合わせて必要な表示が更新されます。Vue.js公式ドキュメント vueframework

キャラクター 「script側で持ち物や検索語を覚えて、template側で一覧画面として見せる。まずはこの往復を追ってみよう。」

Vueの.vueファイルは、今のところ次の3つへ分けて考えています。

  • <script setup>:状態、計算結果、関数、監視処理を書く
  • <template><script setup>の値を読み、画面へ出したり、操作で値を変えたりする
  • <style>:画面上の色・余白・配置などを整える

つまずいたところ

<script setup>の値と<template>で使う値を、同じ場所のデータのように考えないことが大事そうです。

<template>は検索欄や一覧を置く場所ですが、検索語や持ち物データを保管する場所ではありません。検索欄へ入力した文字は、<template>@inputを通って<script setup>keywordへ入り、そこから表示用のcomputedへ渡ります。

この図の流れは、次のように読んでいます。

  1. プレイヤーが<template>の検索欄へ文字を入力する
  2. @input<script setup>keywordを更新する
  3. computeditemskeywordからfilteredItemsを作る
  4. <template>v-forfilteredItemsを一覧として表示する
  5. filteredItemsが0件なら、v-ifが案内文を表示する

ゲームでいうと、itemsは持ち物倉庫、keywordはプレイヤーが入力した検索条件、filteredItemsは現在メニューに並べるアイテム一覧です。v-forは、その一覧を画面上の行やカードとして配置する役割になります。

キャラクター 「templateは倉庫そのものではなくて、script側の倉庫を見ながら、いま必要なアイテムだけをメニューに並べる役なんだね。」

今の理解(メモ)

データの出どころと反映先を分けると、Vue3の要素を次のように整理できそうです。

場所 要素 データの出どころ 反映先・役割 持ち物画面での例
<script setup> ref 初期値、templateからの入力・クリック computed、template keyword、選択中ID、所持金
<script setup> reactive 初期値、templateからの操作 computedv-showなど 検索設定、メニュー設定
<script setup> computed refreactive、元データ v-forv-if{{ }} filteredItems、表示件数
<script setup> watch 指定したリアクティブな値 保存、取得、ログなど 検索語変更後の処理
<script setup> watchEffect 処理内で参照したリアクティブな値 同期処理、ログなど 複数状態を使う処理
<template> {{ }} script側の値 文字として画面表示 アイテム名、検索語、件数
<template> v-bind / : script側の値 HTML属性へ反映 :class:disabled:src
<template> @input / @click プレイヤー操作 script側の値や関数へ渡す 検索語入力、ヘルプ開閉
<template> v-if 真偽値、件数 必要なときだけ要素を表示 0件の案内
<template> v-show 真偽値 要素を残して表示を切替 ヘルプの開閉
<template> v-for 配列・オブジェクト データ数に応じて要素を並べる 持ち物一覧

refは単体のリアクティブな値を作るために使い、<script setup>では.valueで中身を扱います。テンプレートでは通常.valueを書かず、そのまま値を利用できます。Vue.js公式ドキュメント vueframework

computedはリアクティブな依存先から派生した値を作るための仕組みで、依存先が変化するまで結果を再利用します。検索後の一覧や合計値のような「画面に出すための値」に向いていそうです。Vue.js公式ドキュメント vueframework

小さな画面の例

持ち物を検索して一覧を絞り込む例です。コメントで、データが<script setup>から<template>のどこへ届くかを明示します。

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

// 【script:元データ】
// 持ち物倉庫にあるアイテム。
// templateのv-forへ直接渡さず、computedで表示用の配列を作る。
const items = ref([
  { id: 1, name: '木の剣' },
  { id: 2, name: '回復薬' },
  { id: 3, name: '鉄の盾' },
])

// 【script:画面操作で変わる状態】
// templateの検索欄に入力された文字を保存する。
const keyword = ref('')

// 【script:画面に渡す表示用データ】
// itemsとkeywordを使い、templateのv-forとv-ifへ渡す配列を作る。
// itemsまたはkeywordが変わると、Vueがこの結果を更新する。
const filteredItems = computed(() => {
  return items.value.filter((item) => {
    return item.name.includes(keyword.value)
  })
})

// 【script:値の変化後に行う処理】
// keywordが変わったあとに実行される。
// 現時点では確認用のログだけで、外部検索などは追加していない。
watch(keyword, (newKeyword) => {
  console.log('検索語が変わりました:', newKeyword)
})
</script>

<template>
  <section class="inventory">
    <!--
      【script → template】
      :valueでscript側のkeywordを入力欄に表示する。

      【template → script】
      @inputで入力内容をscript側のkeywordへ戻す。
    -->
    <input
      :value="keyword"
      placeholder="アイテム名を検索"
      @input="keyword = $event.target.value"
    >

    <!--
      【script → template】
      filteredItemsが0件のときだけ、この案内を表示する。
    -->
    <p v-if="filteredItems.length === 0">
      条件に合うアイテムはありません。
    </p>

    <!--
      【script → template】
      computedで作ったfilteredItemsをv-forで並べる。
      item.idは、各アイテムをVueが見分けるためのkey。
    -->
    <ul v-else>
      <li v-for="item in filteredItems" :key="item.id">
        {{ item.name }}
      </li>
    </ul>
  </section>
</template>

20260801-001.gif
クリックすると実際の動作を確かめられます

このコードで、itemsは元データ、keywordは検索欄から入る状態、filteredItemsは画面へ渡すために計算したデータです。

操作ごとの流れ

検索欄へ「剣」と入力する

プレイヤーが<template>の検索欄へ「剣」と入力すると、keywordが更新されます。keywordを参照しているfilteredItemsが再計算され、v-forが「木の剣」だけを一覧へ表示します。

検索欄を空に戻す

検索欄を空にすると、keywordは空文字列になります。includes('')はすべてのアイテム名に一致するため、この例ではfilteredItemsへ全アイテムが入り、v-forが3件を表示します。

該当する持ち物がない場合

たとえば「弓」と入力し、該当するアイテムがない場合は、filteredItemsが空配列になります。v-if="filteredItems.length === 0"が真になり、一覧の代わりに案内文を表示します。

watchwatchEffectの位置

この検索画面では、computedが「画面へ出す持ち物一覧」を作っています。一方でwatchwatchEffectは、画面表示そのものではなく、値が変化したあとに処理したいことがある場合に使うものとして整理しています。

  • computeditemskeywordから、画面に表示するfilteredItemsを作る
  • watchkeywordのように、監視する対象を指定して処理する
  • watchEffect:処理の中で使ったリアクティブな値を自動追跡する
  • watchwatchEffect:保存、ログ、データ取得など、画面に値を出す以外の処理を置く

watchは監視対象を明示でき、watchEffectはコールバック内で同期的に読んだリアクティブな依存先を自動で追跡します。Vue.js公式ドキュメント vueframework

キャラクター 「画面の一覧を作るならcomputed。検索語が変わった記録を残すならwatch。どこへ結果を渡したいかで分けると選びやすそう。」

v-showを使う場所

v-showは、<script setup>の真偽値を使い、要素を残したまま表示・非表示を切り替えます。検索のヘルプを頻繁に開閉する場面なら、次のように使えそうです。

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

// script側で、ヘルプを開いているかを持つ
const isHelpOpen = ref(false)
</script>

<template>
  <!-- template側の操作でscript側の状態を変える -->
  <button @click="isHelpOpen = !isHelpOpen">
    ヘルプを開閉
  </button>

  <!-- script側のisHelpOpenを受け取り、見た目だけ切り替える -->
  <p v-show="isHelpOpen">
    アイテム名を入力すると、持ち物一覧を絞り込めます。
  </p>
</template>

v-ifは条件に応じて要素を描画し、v-showは要素をDOMに残したままCSSのdisplayを切り替えます。0件の案内にはv-if、頻繁に開閉するヘルプにはv-showを使う形が分かりやすそうです。Vue.js公式ドキュメント vueframework

次にやりたいこと

今の検索画面を少しずつ広げながら、データの流れを確かめたいです。

  • v-modelを使い、:value@inputをまとめた場合のデータの往復を確認する
  • selectedItemIdrefで持ち、クリックしたアイテムの見た目を:classで変える
  • アイテムに攻撃力を追加し、computedで合計値を作って{{ totalAttack }}へ反映する
  • watchで検索語の変更を受け、検索履歴を保存する形を試す
  • watchEffectで複数の状態を使う処理を書き、watchとの使い分けを確認する
  • v-forで並べたアイテムをItemCard.vueへ渡し、親の配列データが子コンポーネントの画面へ届く流れを試す

今日の整理

Vue3では、データが次の順番で動くものとして整理しています。

操作・きっかけ <script setup>で変わる値 計算・監視 <template>で変わる場所
検索欄へ文字を入力 keyword computed(filteredItems)watch(keyword) v-forの持ち物一覧
検索語が空になる keyword computed(filteredItems) 全アイテムの一覧
該当データが0件になる filteredItems filteredItems.length v-ifの案内文
ヘルプを開閉する isHelpOpen なし v-showのヘルプ
アイテムを選択する selectedItemId 必要に応じてcomputed :classによる選択中の見た目
所持金が変わる gold computed(canBuy) {{ gold }}:disabledの購入ボタン

おわりに

Vue3の要素を機能名だけで覚えるより、<script setup>で作ったデータが<template>のどこへ届くのかを追うと、画面の変化を読みやすくなりました。

今回の持ち物検索画面では、itemsが元データ、keywordがプレイヤー操作で変わる状態、filteredItemsが画面に渡す表示用データ、v-forが画面へ並べる役として分けられました。次はpropsを使い、親コンポーネントのitemsが子コンポーネントのアイテムカードへ渡る流れも確認してみたいです。

学習中の内容なので、勘違いや理解不足もあると思います。もし気になる点があれば教えてもらえるとうれしいです。

 注意事項
 本ブログに掲載している内容は、私個人の見解であり、
 所属する組織の立場や戦略、意見を代表するものではありません。
 あくまでエンジニアとしての経験や考えを発信していますのでご了承ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?