基礎からメモ: Vue.js CH2-p62 クラスとスタイルのデータバインディング

クラスやスタイルの適用

v-bindを使って、HTMLにクラスやスタイルを適用できる。Vueインスタンスのデータ側に、クラスの適用可否やスタイルの内容を設定しておけば、データ側の変更によってクラスやスタイルの変更ができる。

[index06.html]

<p v-bind:class="{ child: isChild, 'is-active': isActive }">Text</p>
<p v-bind:style="{ color: textColor, backgroundColor: bgColor }">Text</p>

[main06.js]

var app = new Vue({
  el: '#app',
  data: {
    isChild: true,
    isActive: true,
    textColor: 'red',
    bgColor: 'lightgray',
  },
})

出力されるHTML

Text

Text

<p class="child is-active">Text</p>
<p style="color: red; background-color: lightgray;">Text</p>

HTML側でのクラス名を、キャメルケースのクラス名はそのままで、ハイフンを含む場合だけクオートで囲っている。これを忘れると次のようなエラーになる。

- invalid expression: Unexpected token - in

    { child: isChild, is-active: isActive }

これはVue.jsの仕様なので忘れないようにする。

プレーンな属性との併記

データバインディングされていない普通の属性がHTML側にある場合、クラス名はマージされ、スタイルセレクターが重なるとVueインスタンスの出力で上書きされたうえでマージされる。結果、プレーンなCSS指定は無視される。

<p class="child" v-bind:class='{ "is-active": isActive }'>Text</p>
<p style="color:green" v-bind:style="{ color: textColor }">Text</p>

出力されるHTML

<p class="child is-active">Text</p> 
<p style="color: red;">Text</p>

ただクラス名が重なる場合、マージされてもプレーンなクラス名は消えず同じクラス名が複数残るので注意。

<p class="child" v-bind:class='{ child: isChild, "is-active": isActive }'>Text</p>

出力されるHTML

<p class="child child is-active">Text</p>

クラス名展開に配列や三項演算子を使用

v-bindでバインドしたクラス名を示す変数がデータ上で配列であれば、展開されて複数のクラス名になる。また三項演算子でクラス名の選択をすることも可能。

<p v-bind:class="[isActive ? 'active' : 'normal', otherClass]">Text</p>

この場合app.isActivetrueならactiveが、falseならnormalが選ばれる。またapp.otherClassotherClass: ['classA', 'classB', 'classC']といった感じで配列になっていると展開されて例えば次のような形になる。

<p class="active classA classB classC">Text</p>

ただし属性に三項演算子を使うのは冗長なので、次のようにオブジェクトデータを使うか、算出プロパティを使うのが良いとのこと。

属性にオブジェクトを渡す

複数のクラスやスタイルを直接HTMLの属性に書くと見にくくなるので、そういうときはdataオプションにオブジェクトで定義し、HTML側にはオブジェクト名で渡す。

<p v-bind:class="classObject">Text</p>
<p v-bind:style="styleObject">Text</p>
// クラスとスタイルのオブジェクト
    classObject: {
      child: true,
      'is-child': true,
      'is-active': false
    }, 
    styleObject: {
      color: 'blue',
      backgroundColor: 'lavender'
    }

この場合、値がtruechildis-childは反映されるが、is-activefalseなので反映されない。

結果のHTML

<p class="child is-child">Text</p>
<p style="color: blue; background-color: lavender;">Text</p>

この方法は当然クラスやスタイル以外の属性データにも使える。たくさんのプロパティをバインドしたいときは、一つひとつ書かずにオブジェクトにまとめて渡すとすっきりする。また次のような引数付きのv-bindを使うと特定の要素をアレンジできる。

<p><img v-bind="item" v-bind:id="'thumb-' + item.id"></p>
    // オブジェクトデータ
    item: {
      id: 1,
      src: "item1.jpg",
      alt: "商品1サムネイル",
      width: 200,
      height: 200
    }

結果のHTML

<p>
    <img id="thumb-1" src="item1.jpg" alt="商品1サムネイル" width="200" height="200">
</p>
  • v-bindを使って、HTMLにクラスやスタイルを適用できる。
  • プレーンな属性との併記では、上書きされマージされる。
  • クラス名展開に配列や三項演算子が使用できる。データ側で配列で定義されたクラス名は複数のクラスに展開される。
  • 複数の属性を直接HTMLに書くときは、dataオプションにオブジェクトで定義しHTML側にはオブジェクト名で渡す。