テンプレート構文
テキストと式
{{ message }} {{ count + 1 }} {{ ok ? 'Yes' : 'No' }}
ディレクティブ
{{ expr }}テキスト補間
v-bind:attr / :attr属性を式にバインド
v-on:event / @eventイベントリスナーをアタッチ
v-model双方向バインディング(フォーム)
v-if / v-else-if / v-else条件付きレンダリング
v-showdisplay CSS を切り替え(DOM に残る)
v-forリストレンダリング
v-slot / #name名前付きスロットコンテンツ
属性バインディング
リアクティビティ
ref(プリミティブ)
import { ref } from 'vue' const count = ref(0) console.log(count.value) // 0 count.value++ // reactive update
reactive(オブジェクト)
import { reactive } from 'vue' const state = reactive({ count: 0, name: 'Vue' }) state.count++ // no .value needed
ref vs reactive
ref()任意の型、スクリプト内では .value でアクセス
reactive()オブジェクト/配列のみ、直接プロパティアクセス
Template両方とも自動アンラップ(.value 不要)
Destructurereactive は分割代入でリアクティビティを失う。toRefs() を使用
算出プロパティとウォッチャー
算出プロパティ
import { ref, computed } from 'vue' const items = ref([1, 2, 3, 4, 5]) const evenItems = computed(() => items.value.filter(n => n % 2 === 0) )

算出値はキャッシュされ、依存関係が変わった時のみ再評価されます

ウォッチャー
import { ref, watch, watchEffect } from 'vue' const query = ref('') // Watch specific source watch(query, (newVal, oldVal) => { console.log(`Changed: ${oldVal} → ${newVal}`) }) // Auto-track dependencies watchEffect(() => { console.log(`Query is: ${query.value}`) })
Watch オプション
immediate: true作成時にコールバックを即時実行
deep: trueネストされたオブジェクトをディープウォッチ
flush: 'post'DOM 更新後に実行
once: true一度だけトリガーして停止
コンポーネント
単一ファイルコンポーネント(SFC)
コンポーネントの登録
SFC のブロック
<script setup>Composition API(推奨)
<template>HTML テンプレート
<style scoped>コンポーネントスコープの CSS
<style module>CSS モジュール($style オブジェクト)
プロップとイベント
プロップの定義
イベントの emit
親での使用
コンポーネントの v-model
スロット
デフォルトスロット

Custom content here

名前付きスロット

Main content

スコープ付きスロット
Composition API
コンポーザブル関数
// useMouse.js import { ref, onMounted, onUnmounted } from 'vue' export function useMouse() { const x = ref(0) const y = ref(0) function update(e) { x.value = e.pageX y.value = e.pageY } onMounted(() => window.addEventListener('mousemove', update)) onUnmounted(() => window.removeEventListener('mousemove', update)) return { x, y } }
コンポーザブルの使用
provide / inject
// Parent import { provide, ref } from 'vue' const theme = ref('dark') provide('theme', theme) // Descendant (any depth) import { inject } from 'vue' const theme = inject('theme', 'light') // default
ルーター(Vue Router)
ルートの定義
import { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', component: Home }, { path: '/about', component: About }, { path: '/user/:id', component: User }, ] })
テンプレートでのナビゲーション
Home User 1
プログラムによるナビゲーション
import { useRouter, useRoute } from 'vue-router' const router = useRouter() const route = useRoute() router.push('/about') router.push({ name: 'user', params: { id: 1 } }) console.log(route.params.id)
ルート機能
/user/:id動的セグメント(route.params.id
name: 'user'プログラムナビゲーション用の名前付きルート
children: [...]ネストされたルート
beforeEnterルートごとのナビゲーションガード
meta: { auth: true }ガード用カスタムメタデータ
redirect: '/new-path'ルートのリダイレクト
ライフサイクルフック
フックの順序
onBeforeMount初期 DOM レンダリング前
onMountedDOM 準備完了(データ取得、リスナー追加)
onBeforeUpdateリアクティブ状態が DOM を再レンダリングする前
onUpdatedDOM 再レンダリング後
onBeforeUnmountコンポーネントが破棄される前
onUnmountedクリーンアップ(リスナー、タイマーの削除)
使用方法
リストと条件
v-for
  • {{ item.name }}
  • {{ index }}: {{ item.name }}
  • {{ key }}: {{ val }}

    効率的な DOM 更新のために v-for では常に :key を使用してください

    v-if vs v-show
    v-if条件付きレンダリング(DOM への追加/削除)
    v-else-ifelse-if チェーン
    v-elseフォールバックブランチ
    v-showdisplay: none を切り替え(DOM に残る)

    頻繁な切り替えには v-show、まれな変更には v-if を使用

    条件の例
    Loading...
    Error!
    {{ data }}
    フォーム処理
    v-model の基本
    v-model 修飾子
    v-model.lazyinput の代わりに change で同期
    v-model.number自動的に数値にキャスト
    v-model.trim自動的に空白をトリム
    イベント修飾子
    @click.preventpreventDefault() を呼び出す
    @click.stopstopPropagation() を呼び出す
    @click.once最大 1 回だけトリガー
    @keyup.enterEnter キーのみ
    @submit.preventフォーム送信のデフォルトを防止