この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:guest
更新日時:2026-06-11 07:10:02

タイトル: v-bindによるデータ連携
SEOタイトル: Vue.js v-bind 完全ガイド (属性 / クラス / スタイル / Composition API)

この記事の要点
  • v-bind:href="url" = HTML 属性に JS の値をバインド。短縮形は :href="url"
  • クラスの動的切替: :class="{ active: isActive }" (オブジェクト) / :class="[cls1, cls2]" (配列)
  • スタイルの動的切替: :style="{ color: textColor, fontSize: size + "px" }"
  • v-bind="objWithMultipleProps" でオブジェクト全プロパティを一括バインド
  • Composition API では ref / computed の値が : 経由で自動 unwrap

v-bind の基本

v-bind は HTML 属性の値を JavaScript 式で動的に決定するための Vue ディレクティブです。短縮形 : が広く使われます。

<template>
    <!-- 完全形 -->
    <a v-bind:href="url">リンク</a>

    <!-- 短縮形 (推奨) -->
    <a :href="url">リンク</a>

    <!-- 複数の属性 -->
    <img :src="imageUrl" :alt="imageAlt" :width="width">

    <!-- 動的な属性名 (Vue 2.6+) -->
    <button :[attrName]="attrValue">動的</button>

    <!-- Boolean 属性 (true なら属性追加、false なら削除) -->
    <button :disabled="isLoading">送信</button>
    <input :readonly="!editable">
</template>

<script setup>
import { ref } from 'vue';
const url = ref('https://example.com');
const imageUrl = ref('/img/logo.png');
const isLoading = ref(false);
</script>

クラスバインディング

<template>
    <!-- オブジェクト構文: キー=クラス名、値=真偽値 -->
    <div :class="{ active: isActive, disabled: !enabled }">...</div>

    <!-- 配列構文 -->
    <div :class="[baseClass, themeClass]">...</div>

    <!-- 配列内オブジェクト -->
    <div :class="[baseClass, { active: isActive }]">...</div>

    <!-- 三項演算子 -->
    <div :class="isError ? 'text-red' : 'text-green'">...</div>

    <!-- computed と組み合わせ -->
    <div :class="classObject">...</div>
</template>

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

const isActive = ref(true);
const enabled = ref(false);
const baseClass = ref('btn');
const themeClass = ref('btn-primary');

const classObject = computed(() => ({
    active: isActive.value,
    'text-danger': hasError.value,
}));
</script>

スタイルバインディング

<template>
    <!-- オブジェクト構文(キーはキャメルケース or ケバブケース) -->
    <div :style="{ color: textColor, fontSize: size + 'px' }">...</div>
    <div :style="{ 'background-color': bg }">...</div>

    <!-- 配列で複数オブジェクト -->
    <div :style="[baseStyles, overrideStyles]">...</div>

    <!-- CSS 変数 (CSS Custom Properties) -->
    <div :style="{ '--main-color': mainColor }">...</div>

    <!-- ベンダープレフィックス自動付与 -->
    <div :style="{ transform: 'translateX(' + offset + 'px)' }">...</div>

    <!-- 配列値で fallback -->
    <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">...</div>
</template>

<script setup>
import { ref } from 'vue';
const textColor = ref('#333');
const size = ref(16);
const offset = ref(100);
</script>

オブジェクトを一括バインド

<template>
    <!-- 個別 -->
    <input :id="form.id" :type="form.type" :value="form.value" :name="form.name">

    <!-- 一括バインド (v-bind に引数なし) -->
    <input v-bind="form">

    <!-- スプレッド的に使える -->
    <BlogPost v-bind="post" />
    <!-- 上記は <BlogPost :id="post.id" :title="post.title" ... /> と等価 -->
</template>

<script setup>
import { ref } from 'vue';
const form = ref({
    id: 'username',
    type: 'text',
    value: 'taro',
    name: 'user',
});

const post = ref({
    id: 1,
    title: 'はじめての Vue.js',
    author: '田中',
});
</script>

v-bind の修飾子

修飾子意味
.prop属性ではなく DOM プロパティとしてバインド:innerHtml.prop="html"
.attr明示的に HTML 属性として (Vue 3):value.attr="val"
.camelケバブケース属性名をキャメルに:view-box.camel="box"
.sync (Vue 2)双方向バインド (v-model:propName で代替)非推奨

Composition API での ref / computed 連携

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

// ref: プリミティブの reactive ラッパー
const count = ref(0);
const isAdmin = ref(false);

// テンプレート内では自動 unwrap (.value 不要)
// <p :data-count="count">  ← count.value ではなく count

// computed: 派生値
const doubled = computed(() => count.value * 2);
const labelClass = computed(() => ({
    active: count.value > 0,
    danger: count.value > 100,
}));

// reactive: オブジェクトの reactive ラッパー
const user = reactive({
    name: '田中',
    age: 30,
});

// 関数で動的な値
function buttonClass(idx) {
    return {
        active: idx === selectedIdx.value,
        first: idx === 0,
    };
}
</script>

<template>
    <p :data-count="count">{{ doubled }}</p>
    <span :class="labelClass">ラベル</span>
    <div :data-user-name="user.name">...</div>
    <button v-for="(item, i) in items" :class="buttonClass(i)">
        {{ item }}
    </button>
</template>

typical use cases

シーンv-bind の使い方
ボタンの活性状態:disabled="loading"
選択中タブのハイライト:class="{ active: tab === current }"
動的画像:src="userAvatar"
テーマカラー:style="{ '--brand': brandColor }"
進捗バー:style="{ width: percent + '%' }"
属性ホワイトリスト一括v-bind="$attrs" (透過)
外部リンク区別:target="isExternal ? '_blank' : null"

v-bind と v-on (双方向: v-model)

<template>
    <!-- v-bind + v-on で擬似 v-model -->
    <input :value="name" @input="name = $event.target.value">

    <!-- v-model はその短縮 (Vue 3) -->
    <input v-model="name">

    <!-- 子コンポーネントへの v-model (Vue 3) -->
    <CustomInput v-model="form.email" v-model:label="form.label" />
    <!-- 子側: defineProps(['modelValue', 'label']) + emit('update:modelValue', val) -->
</template>

よくあるミス

ミス正解
:href="{{ url }}":href="url" (二重カッコ不要)
href="{{ url }}":href="url" (Mustache は属性に使えない)
:class="active" (文字列のつもり):class="'active'" または class="active"
:style="color: red":style="{ color: 'red' }"
true/false なのに残るBoolean 属性に v-bind を使う

FAQ

Q: v-bind{{ }} の違いは?
A: {{ }} (Mustache) はテキストコンテンツ専用。属性値には使えないので v-bind (短縮 :) を使います。

Q: クラスを class と :class 両方書ける?
A: 可能。Vue は両者をマージします。<div class="base" :class="{ active: x }"> は OK。

Q: v-bind="$attrs" って何?
A: 親から渡されたが props として宣言していない属性すべてを子要素にパススルー。ラッパーコンポーネントで定番。