採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

Vue — Template 補間

テクノロジ系 / L01 template-syntax — テンプレート構文

Vue — Template 補間

{{ }} でデータを画面に映す

この章を終えると、できること

  • {{ }}(マスタッシュ)を使って、JavaScript のデータを画面に表示できる
  • {{ }} の中に 計算や呼び出し(式) を書いて、結果を表示できる
  • データを書き換えると 画面が自動で変わる(リアクティブ)感覚をつかむ

> 完成イメージ:const name = "Vue" と書いたデータが、

> 画面に Hello, Vue と出る。name を変えれば表示も変わる。

この一点だけに集中します。属性(:src など)やボタンの本格的な扱いは次章以降

なぜ学ぶ? — 「値を直接書く」と何が困るか

例:見出しに名前を出したい。素の HTML なら、こう書く 👇

<h1>Hello, Taro</h1>

一見これで十分。でも、こんなときに困ります。

  • 名前が 後で変わる(ログインしたユーザーごとに違う)
  • 同じ値を何度も使う(あちこちに名前を出す)
  • 値を 計算したい(合計金額、件数 …)

Taro を直接書いてしまうと、変わるたびに HTML を手で書き直すことになります。

解決策:値は「データ」に置き、画面には差し込む

直接書く代わりに、値を変数(データ)に入れて、画面には {{ }}差し込みます。

<script setup lang="ts">
const name = "Taro";   // ← 値はここに 1 か所だけ
</script>

<template>
  <h1>Hello, {{ name }}</h1>   <!-- ← ここに差し込まれる -->
</template>

> 📺 画面の表示:Hello, Taro

name"Hanako" に変えれば、画面は Hello, Hanako に変わります。

値は 1 か所、表示はそこを見るだけ。 これが補間(ほかん)です。

いま出てきた .vue ファイルの正体

Vue では、見た目とデータを 1 つのファイルにまとめて書きます。

このファイルを SFC(Single File Component) と呼びます(=部品 1 つ=1 ファイル)。

<script setup lang="ts">   <!-- ① データやロジック(JavaScript) -->
const name = "Taro";
</script>

<template>                  <!-- ② 画面(HTML) -->
  <h1>Hello, {{ name }}</h1>
</template>

<style scoped>             <!-- ③ 見た目(CSS)。この章では飾り、気にしなくてOK -->
h1 { color: blue; }
</style>

> 🔰 今は <script setup><template> の 2 つだけ見れば十分。

> lang="ts"(TypeScript)や scoped(この部品だけに効く CSS)は飾り。後で学びます。

図解:データが画面に届くまで

<script setup> に書いた変数は、同じファイルの <template> からそのまま使えます

return や受け渡しの記述は不要。Vue が自動でつないでくれる)

flowchart LR
  A["script setup<br/>const name = 'Taro'"] -->|名前で参照| B["template<br/>マスタッシュで name を参照"]
  B -->|Vue が置き換え| C["画面<br/>Hello, Taro"]

> 💡 ポイント:{{ name }} は「ここに name の中身を入れて」という目印

> Vue がその目印を、name の値(Taro)に置き換えて画面に出します。

まず動かして確かめよう(独学者向け)

頭で追うより、動かすのが一番速いです。L00 で作った環境を使います。

  1. src/App.vue を開き、中身を上の SFC 例で丸ごと置き換える
  2. ターミナルで開発サーバを起動:
npm run dev
  1. 表示された URL(例 http://localhost:5173)をブラウザで開く
  2. 画面に Hello, Taro が出れば成功 ✅

> 🧪 確認のコツ:name の値を書き換えて保存すると、

> ブラウザが自動で更新され、表示も変わります。これを何度か試すと感覚がつかめます。

{{ }} の中身は「式」 — 計算や呼び出しもできる

{{ }} には変数名だけでなく、JavaScript の式が書けます。

<template>
  <p>{{ message }}</p>                     <!-- 変数そのまま -->
  <p>{{ count + 1 }}</p>                    <!-- 足し算 -->
  <p>{{ user.name.toUpperCase() }}</p>      <!-- メソッド呼び出し -->
  <p>{{ items.length }} 件</p>              <!-- プロパティ参照 -->
  <p>{{ isAdmin ? "管理者" : "一般" }}</p>  <!-- 三項演算子 -->
</template>

> どれも「計算した結果の値」が画面に出ます。

> count4 なら count + 15 と表示。

> 📋 これ以降のコードは説明用の <template> 抜粋です。そのまま貼っても

> message is not defined で動きません。動かすときは <script setup> 側に

> const message = "..." のように使う変数を自分で用意してください。

つまずき先回り:「式」って何?「文」とどう違う?

{{ }} の中に書けるのは 式(しき)だけ文(ぶん)は書けません

ここが最初の関門なので、見分け方をはっきりさせます。

正体{{ }} の中
計算すると値が 1 個残るもの1 + 2(→ 3), name.toUpperCase()✅ 書ける
「〜せよ」という命令if (a) {...}, const x = 1, for (...)❌ 書けない

> 🔑 見分け方:そのコードを「= の右側に置けるか?」

> const r = (1 + 2) は OK → const r = (if ...) はおかしい →

{{ }} は「最後に値が 1 個残る場所」とだけ覚えればOK。

「式は1つだけ」 — OK と NG

{{ }} に入れられるのは、値が 1 個に決まる1 つの式だけです。

<template>
  <p>{{ a + b }}</p>                       <!-- ✅ 値が1個 -->
  <p>{{ items.filter(x => x > 0).length }}</p> <!-- ✅ つながっても結果は1個 -->

  <p>{{ let x = 1; x + 1 }}</p>            <!-- ❌ 変数宣言は「文」 -->
  <p>{{ if (a) "yes" }}</p>                <!-- ❌ if は「文」 -->
</template>

> ⚠️ NG が出たら「これは命令(文)を書いていないか?」を疑う。

> 計算が複雑になりすぎたら、<script> 側で計算してから {{ }} で呼びます

> (その専用の仕組み computed は ch01 の後半/別レッスンで学びます)。

おまけ:v-text{{ }} と同じ意味

同じ「値を差し込む」書き方に v-text もあります。意味は {{ }} と同じです。

<p>{{ message }}</p>          <!-- これと -->
<p v-text="message"></p>      <!-- これは同じ結果 -->

> 🔰 迷ったら {{ }} を使えばOK。 普段は {{ }} だけで困りません。

> v-text は「タグの中身を丸ごと差し替えたい」特殊な場面で使う、と頭の隅に置く程度で十分。

⚠️ 関連して、v-html(文字列を HTML として描き込む)という危ないものもあります。

他人が用意した文字列に使うと攻撃される危険(XSS)があるため、専用の安全な章で改めて扱います。

つまずき先回り:{{ }} はタグの中身専用

{{ }} が使えるのは、タグとタグに挟まれた中身(テキスト)だけです。

属性(srchref など)の中には書けません。

<template>
  <h1>{{ title }}</h1>           <!-- ✅ 中身ならOK -->

  <img src="{{ imageUrl }}" />   <!-- ❌ 属性には書けない -->
</template>

> 🧯 src="{{ imageUrl }}" と書くと、{{imageUrl}} という文字そのまま

> URL として扱われ、画像は出ません(壊れた画像になる)。

属性に変数を入れたいときは、{{ }} ではなくコロン : を付けます👇

属性に変数を入れたいとき(予告)

属性は別ルール。:属性名="式" と書きます(この :v-bind と呼びます)。

<template>
  <img :src="imageUrl" :alt="imageAlt" />   <!-- ✅ 属性はコロン -->
</template>
flowchart LR
  A["タグの<b>中身</b>に値を入れる"] --> M["{{ }} マスタッシュ"]
  B["<b>属性</b>に値を入れる"] --> C[": コロン (v-bind)"]

> 📍 住み分け:中身は {{ }}、属性は :

> :src:class:style詳しい使い方は次章 ch02-v-bind で扱います。

> この章では「属性のときはコロン」と知っておけば十分です。

値が変わると画面も変わる = リアクティブ

ここまでの const name = "Taro"変わらない値でした。

「後で値を変えて、画面にも反映したい」ときは、値を ref() で包みます。

<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);   // ← ref で包むと「変化を見張れる」データになる

function increment() {
  count.value++;        // ← script 側で書き換えるときは .value が必要
}
</script>

<template>
  <p>カウント: {{ count }}</p>   <!-- テンプレートでは .value 不要(Vue が補う) -->
</template>

> 🔁 ref で包んだ値を後から書き換えると、Vue が画面を自動で更新します。

> これを リアクティブ と呼びます。

>

> ⚖️ .value の使い分け<script> の中で読み書きするときは count.value

> <template> の中では count だけ(.value 不要)。最初は混乱しやすいので、

> 「script 側は .value 付き、画面側は付けない」と覚えておけば十分です。

> ref の詳しい仕組みは後の章で学びます。

動く実感:押すと増えるカウンター

ref の嬉しさが一番わかる最小デモです(ボタンの @click次章 ch03 で詳しく)。

<script setup lang="ts">
import { ref } from "vue";
const count = ref(0);
</script>

<template>
  <p>{{ count }}</p>
  <button @click="count++">+1</button>   <!-- 押すと count が増える -->
</template>

> 🧪 npm run dev で開いてボタンを押すと、{{ count }} の数字がその場で増えます

> countref でなく const count = 0 にすると…増えても画面は変わりません

> この違いこそが「リアクティブ」。手元で両方試すと腹落ちします。

> 🤔 「あれ、count++ ってじゃないの?さっき {{ }} の中は式だけって…」

> 鋭い疑問です。ルールが違う場所だから OK なのです。

> 「式だけ」の制限は {{ }} の中だけの話。@click="..."(イベント)の中は

> 別ルールで、count++ のような代入や命令も書けます(詳細は次章 ch03)。

ボタンを押してから画面が変わるまで

「クリックしたら勝手に画面が変わる」と書きましたが、内部では順番に4ステップが起きています。時系列で見ると腹落ちします。

sequenceDiagram
  actor ユーザー
  participant ボタン as ボタン (template)
  participant データ as count (ref)
  participant 画面 as 画面表示
  ユーザー->>ボタン: ① クリック
  ボタン->>データ: ② count++ で値を +1
  データ->>画面: ③ 変化を検知 (リアクティブ)
  画面-->>ユーザー: ④ 新しい数字を表示

> 💡 あなたが書くのは ② の @click="count++" だけ。③④ の「変化を検知して画面を描き直す」は Vue が自動でやってくれます。これがフレームワークを使う嬉しさです。

まとめ — この章でできるようになったこと

  • {{ }}(マスタッシュ)で、データを画面の中身に差し込める
  • {{ }} の中には 式(値が1個に決まるもの)が書ける。文(命令)はNG
  • <script setup> の変数は、同じファイルの <template> からそのまま使える
  • ✅ 属性に入れるときは {{ }} でなく コロン :(詳細は次章)
  • ✅ 後で変える値は ref で包む → 変えると画面も自動更新(リアクティブ)
flowchart LR
  D["データ<br/>(script setup)"] -->|マスタッシュで差し込み| V["画面 (template)"]
  D -. "ref なら値の変化で自動更新" .-> V

> 🚪 次は ch02-v-bind:属性に値を入れる :(v-bind)と、:class:style を本格的に。

> その後 ch03 でボタンの @click(イベント)を詳しく扱います。

考えてみよう

既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。

Lv1: 基本 — マスタッシュ

問題

<script setup lang="ts">
const name = "Taro";
const age = 20;
const items = ["apple", "banana"];
</script>

<template>
  <h1>{{ name }} ({{ age }}歳)</h1>
  <p>{{ name.toUpperCase() }}</p>
  <p>{{ age * 2 }}</p>
  <p>{{ items.length }} items</p>
  <p>{{ items.join(", ") }}</p>
</template>

合格基準

5行全部期待通りに描画。

Lv2: 応用 — class / style バインディング

問題

<script setup lang="ts">
const isActive = ref(true);
const hasError = ref(false);
const color = ref("red");
</script>

<template>
  <div :class="{ active: isActive, error: hasError }">Class object</div>
  <div :class="[isActive ? 'active' : '', hasError ? 'error' : '']">Class array</div>
  <div :style="{ color, fontSize: '20px' }">Style</div>
  <button @click="isActive = !isActive">Toggle</button>
  <button @click="color = color === 'red' ? 'blue' : 'red'">Color</button>
</template>

合格基準

  • class / style バインディングが切り替わる
  • 2ボタンで動的に反映

Lv3: 発展 — v-html の危険性

問題

<script setup>
const userInput = ref("<img src=x onerror=alert('XSS') />");
</script>

<template>
  <p>{{ userInput }}</p>            <!-- ✅ 文字列として描画 -->
  <p v-html="userInput"></p>         <!-- ❌ alert が走る -->
</template>

両方試して、v-html で XSS が走ることを観察。

「v-html は 信頼できるソースだけ」を 100字で説明。

合格基準

  • {{ }} は安全、v-html は危険、を体感
  • ルールを言語化

提出

submission.md に3問の回答を。