【Vue.js】 #2 v-bind ディレクティブ

ディレクティブとは

ディレクティブとは、v-で始まる属性のことでdrective(指令)という名前の通り、Vue.jsに何らかの支持を行う仕組みになります。
Vue.jsには多くのディレクティブがありますが、下記ではv-bindディレクティブについて紹介いたします。

【v-bind】属性へのバインディング

HTMLのvalue属性やstyle属性、href属性等の属性へのバインディングを行う場合、v-bindディレクティブを使用します。下記のようにvalue属性やクラス属性をバインディングするプログラムを作成します。

See the Pen [v-bind] 属性へのデータバインディング by kenichiro ikeuchi (@ken_ikeuchi) on CodePen.

サンプルコード 解説

<div id="app">
  <!-- value属性バインディング-->
  <input type="text" v-bind:value="text_caption">
  
  <!-- [オブジェクト構文 例1] -->
  <div v-bind:class="{ font_large: large_flg }">
    文字サイズサンプル(大)
  </div>
  
  <!-- [オブジェクト構文 例2] -->
  <div class="static" v-bind:class="{ active: active_flg, text_warning: warning_flg}"
>
    注意色サンプル
  </div>
  
  <!-- [オブジェクト構文 例3] -->
  <div class="static" v-bind:class="dangerObject">
    警告文字サンプル
  </div>
  
  <!-- [配列構文 例1] -->
  <div>
    <span>テストメッセージ:</span>
    <span v-bind:class="[activeClass,dangerClass]">
      警告テスト
    </span>
  </div>
</div>
const app = Vue.createApp({
  data: () => ({
    
    // テキストへの文字列表示設定
    text_caption: '表示テスト',
    
    // 文字サイズサンプル(大)設定プロパティ
    large_flg: true,
    
    // 注意色サンプル 設定プロパティ
    active_flg: false,
    warning_flg: true,
    
    // 警告文字サンプル 設定プロパティ
    dangerObject: {
      active: true,
      text_danger: true
    },
    
    // 警告テスト 設定プロパティ
    activeClass: 'font_large',
    dangerClass: 'text_danger'
    
  })
})
app.mount('#app')
/*文字サイズ設定*/
.font_large{
  font-size:32px;
}

/*activeクラス指定時*/
.active{
  font-weight:bold;
}

/*文字色パターン設定*/
.text_warning{
  color:#FFC607; /* 注意色*/
}
.text_danger{
  color:red;    /* 警告色*/
}

1.属性へのバインディング方法

前回ではマスタッシュ構文を用いて、テキストへのバインディングを行いましたが、属性へのバインディングの場合、{{ }}というマスタッシュ構文は使用することができません。
テキストボックス等、value属性へバインディングを行う場合は下記のように記述します。

<div id="app">
  <!-- value属性バインディング-->
  <input type="text" v-bind:value="text_caption">
</div>
<div v-bind:属性名="プロパティ名">

今回バインディングを行うのはinputタグのvalue属性なので属性valueの前に、v-bind:をつけます。次に属性の値には、dataoptionに設定していたプロパティー名(今回はtext_caption)を指定します。

const app = Vue.createApp({
  data: () => ({
    // テキストボックスへの文字列表示設定
    text_caption: '表示テスト'
  })
})
app.mount('#app')

次にJs側にプロパティを定義してプロパティの内容を設定します。
以上で、下記のようにJs側に設定したプロパティの内容をバインディングさせることができます。

【実行結果】

2.オブジェクト構文

属性へのバインディング方法ですが、HTML側で記述する際に上記以外にもオブジェクトを使用した記述方法があるので下記に紹介していきます。

<div id="app">
  <!-- [オブジェクト構文 例1] -->
  <div v-bind:class="{ font_large: large_flg }">
    文字サイズサンプル(大)
  </div>
</div>
const app = Vue.createApp({
  data: () => ({
    // 文字サイズサンプル(大)設定プロパティ
    large_flg: true,
  })
})
app.mount('#app')
/*文字サイズ設定*/
.font_large{
  font-size:32px;
}
<div v-bind:class="{ 付与したいクラス名:プロパティ名 }">

上記のように、クラス属性の値を指定する際に { } のオブジェクトを渡すことでクラスを動的に切替えることができます。
上の構文は、class 属性に font_large というクラス名を付与するかどうかを、Js側のdataoptionに定義したプロパティ名 large_flg の真偽性 (true、false) によって決めることを意味しています。
今回は large_flg プロパティをtrueで設定しているので、真となり font_large クラスがクラス属性に付与され、結果として下記のようにバインディングされます。

<div class="font_large">文字サイズサンプル(大)</div>

次に、これはVue.jsの機能とは別になりますがHTMLのクラス属性に font_large クラスが付与されたことにより、CSSファイルで設定していたスタイルシートが適用されます。今回のスタイルシートには font_large クラスの文字サイズを32pxに指定していますので、下記のような32pxの文字サイズで表示されます。

【実行結果】


ちなみに複数のクラスをオブジェクト構文を使って付与したい場合は { } 内を , (カンマ)で区切って、次のような形になります。

<div id="app">
  <!-- [オブジェクト構文 例2] -->
  <div class="static" v-bind:class="{ active: active_flg, text_warning: warning_flg}"
>
    注意色サンプル
  </div>
</div>
const app = Vue.createApp({
  data: () => ({
    // 注意色サンプル 設定プロパティ
    active_flg: false,
    warning_flg: true
  })
})
app.mount('#app')
/*activeクラス指定時*/
.active{
  font-weight:bold;
}

/*文字色パターン設定*/
.text_warning{
  color:#FFC607; /* 注意色*/
}

このサンプルでは、バインディングによってactiveクラスが付与されたら文字を太字に、text_warningクラスが付与されたら文字を色を変えるという動作になりますが、Js側でactive_flgがfalseに設定されているので、真偽性 (true、false)の判定で偽となり、activeクラスは付与されません。
そのため、バインディング後のHTMLは下記のような形になります。

<div class="static text_warning">注意色サンプル</div>

バインディングの結果としてクラス属性には元々指定していたstaticクラスとJs側でwarning_flgがtrue設定されていたtext_warningクラスのみが付与されています。その結果、上のCSS側で文字色を変える部分のスタイルシートのみHTML要素に適用されています。最終的な表示としては次のようになります。

【実行結果】

また、上の書き方でオブジェクト構文を使って複数のクラスの付与判定をしていくとHTML側のバインド部分が長くなり可読性が落ちるため、次のようにまとめる事もできます。

<div id="app">
  <!-- [オブジェクト構文 例3] -->
  <div class="static" v-bind:class="dangerObject">
    警告文字サンプル
  </div>
</div>
const app = Vue.createApp({
  data: () => ({
    // 警告文字サンプル 設定プロパティ
    dangerObject: {
      active: true,
      text_danger: true
    }
  })
})
app.mount('#app')
/*activeクラス指定時*/
.active{
  font-weight:bold;
}

/*文字色パターン設定*/
.text_danger{
  color:red;    /* 警告色*/
}

Js側のdataoption内で下記のように複数のプロパティを纏めたオブジェクトを定義します。

// 警告文字サンプル 設定プロパティ
dangerObject: {
  active: true,
  text_danger: true
}

activeプロパティとtext_dangerプロパティの両方がtrueに設定されているため、HTML側に下記のように下記のようにバインディングされます。

<div class="static active text_danger"> 警告文字サンプル </div>

上のように クラス属性にactiveとtext_dangerが付与されています。この書き方の場合はJs側のdangerObject の中に定義したプロパティ名がクラス名として付与されることになります。

また、今回はactiveとtext_danger両方のクラスが付与されているので、上のCSSで設定したfont-weight:boldの太字指定とcolor:redの文字色指定の両方が適用され、最終的な表示としては次のようになります。

【実行結果】

2.配列構文

次に属性へのバインディング方法で配列を使うこともできるので下記のように紹介します。

<div id="app">  
  <!-- [配列構文 例1] -->
  <div>
    <span>テストメッセージ:</span>
    <span v-bind:class="[activeClass,dangerClass]">
      警告テスト
    </span>
  </div>
</div>
const app = Vue.createApp({
  data: () => ({   
    // 警告テスト 設定プロパティ
    activeClass: 'font_large',
    dangerClass: 'text_danger'
  })
})
app.mount('#app')
/*文字サイズ設定*/
.font_large{
  font-size:32px;
}
/*文字色パターン設定*/
.text_danger{
  color:red;    /* 警告色*/
}

HTML側の書き方としては以下のような形になります。

<span v-bind:class="[プロパティ名,プロパティ名]">

上のように [ ] 内にJs側で定義しているプロパティ名を ,(カンマ)で設定していきます。

完了したら下記のようにJs側のプロパティで設定されている値がHTML側のクラス属性にバインディングされます。

<span class="font_large text_danger"> 警告テスト </span>

クラス名はJs側で設定されているプロパティの値になります。

また、今回はfont_largeとtext_dangerのクラスが付与されているので、上のCSSで設定したfont-size:32pxの文字サイズ指定とcolor:redの文字色指定がspanタグに適用され、最終的な表示としては次のようになります。

【実行結果】

上の配列構文では配列リスト [ ] にJs側のプロパティを設定していますが、リスト内でのクラス名の付与を条件に応じて切り替えたい場合は、三項演算子式を使用したり、リスト内にオブジェクト構文を使用することで、実現することができます。
より詳細な三項演算子式の使い方やオブジェクト構文の併用方法等の内容につきましては、下記を参照いただければと思います。
【参考記事】
・MDN Web Docs - 条件 (三項) 演算子 -
・Vue3 公式ドキュメント -配列構文-

補足

今回は上で紹介しませんでしたが、v-bindを使用してstyle属性にインラインスタイルのバインディングも行うことができます。※ v-bind : の部分は : に省略することができます。

<div :style="{ color: mainColor, fontSize: fontSize + 'px' }"></div>
const app = Vue.createApp({
  data: () => ({
    mainColor: 'blue',
    fontSize: 30
  })
})

またはオブジェクト部分をまとめて下記のようにも記述できます。

<div :style="styleObject"></div>
const app = Vue.createApp({
  data: () => ({
    styleObject: {
      color: 'blue',
      fontSize: '30px'
    }
  })
})

どちらもバインディング後のHTMLは下記のように同じになります。

<div style="color:blue; fontSize:30px;"></div>

上のファイルを見るとHTMLファイルやJavaScriptファイルの中にも、CSSファイルで設定するようなスタイル情報が記述されてしまっています。

そのような場合、デザインの追加や修正が発生した際に両方のファイルを変更しないといけなくなるため、修正漏れが発生しやすくなる事もあるので注意が必要です。

今回のサンプルコードでは、なるべくクラスを付与することによってCSSファイルに記述している情報を読み出し、文字色や文字サイズ等のスタイル情報をHTML側へ適用してきました。

最近ではレスポンシブに柔軟に対応するため、TailwindCSSやBootstrap5でも下記のようにクラスを付与していくことで様々なレイアウトが組まれています。

<!-- TailwindCSS -->
<button class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded">
  Button
</button>

<!-- Bootstrap -->
<button class="d-none pr-0 float-left float-md-none">
  Button
</button>

ただこれも、気を付けないとクラス名がどんどん増えていって可読性が悪くなったりもするので、現場では注意が必要かもしれません。

なるべく、HTML構造とデザイン部分は分けることが推奨されていますので、開発現場でCSSの使い方やインラインスタイルを使用する時のルールはしっかり確認することが必要だと思います。

<div class="static" v-bind:class="{ active: active_flg ,'text-warning': warning_flg}"文字(大)</div>

また、今回はクラス名の単語連結に – (ハイフン)を使うと上のようにtxet-warningの部分を ‘ ‘(シングルクォート)で囲わないといけないので _ (アンダースコア)を使っていますが、SEOの観点からCSSに記述する時は単語連結に _ (アンダースコア)は非推奨となります。より詳しいTailwindCSSやBootstrap5、スタイルシートについての説明は下記を参考にしてもらえたらと思います。

【参考記事】
・Bootstrap5 ドキュメント
・TailwindCSS
・CSSはSEOに影響する!GoogleのCSSガイダンスに沿ったコーディングを目指そう

投稿者プロフィール

IkeuchiKenichiro

関連記事

  1. 【Vue.js】 #1 はじめに

最近の記事

  1. flutter
  2. GAS
  3. flutter
  4. flutter
  5. etc

制作実績一覧

  1. Checkeys