# クラスとスタイルのバインディング
データバインディングに一般に求められることの 1 つは、要素のクラスリストとインラインスタイルを操作することです。それらはどちらも属性であるため、v-bind
を使って扱うことができます。最終的な文字列を式で計算するだけです。しかしながら、文字列の連結に手を出すのは煩わしく、エラーのもとです。そのため、Vue は v-bind
が class
と style
と一緒に使われるとき、特別な拡張機能を提供します。文字列だけではなく、式はオブジェクトまたは配列を返すことができます。
# HTML クラスのバインディング
# オブジェクト構文
:class
(v-bind:class
の略) にオブジェクトを渡すことでクラスを動的に切り替えることができます:
<div :class="{ active: isActive }"></div>
上記の構文は、active
クラスの有無がデータプロパティ isActive
の真偽性によって決まることを意味しています。
オブジェクトにさらにフィールドを持たせることで複数のクラスを切り替えることができます。加えて、:class
ディレクティブはプレーンな class
属性と共存できます。つまり、次のようなテンプレートと:
<div
class="static"
:class="{ active: isActive, 'text-danger': hasError }"
></div>
2
3
4
次のようなデータがあったとすると:
data() {
return {
isActive: true,
hasError: false
}
}
2
3
4
5
6
このように描画されます:
<div class="static active"></div>
isActive
もしくは hasError
が変化するとき、クラスリストはそれに応じて更新されます。例えば、hasError
が true
になった場合、クラスリストは "static active text-danger"
になります。
束縛されるオブジェクトはインラインでなくてもかまいません:
<div :class="classObject"></div>
data() {
return {
classObject: {
active: true,
'text-danger': false
}
}
}
2
3
4
5
6
7
8
これは同じ結果を描画します。オブジェクトを返す算出プロパティに束縛することもできます。これは一般的で強力なパターンです:
<div :class="classObject"></div>
data() {
return {
isActive: true,
error: null
}
},
computed: {
classObject() {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配列構文
:class
に配列を渡してクラスのリストを適用することができます:
<div :class="[activeClass, errorClass]"></div>
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
2
3
4
5
6
これは次のように描画されます:
<div class="active text-danger"></div>
リスト内のクラスを条件に応じて切り替えたい場合は、三項演算子式を使って実現することができます:
<div :class="[isActive ? activeClass : '', errorClass]"></div>
この場合 errorClass
は常に適用されますが、activeClass
クラスは isActive
が真と評価されるときだけ適用されます。
しかしながら、これでは複数の条件つきクラスがあると少し冗長になってしまいます。そのため、配列構文の内部ではオブジェクト構文を使うこともできます:
<div :class="[{ active: isActive }, errorClass]"></div>
# コンポーネントにおいて
このセクションでは、Vue のコンポーネントの知識を前提としています。いったんスキップして後で戻ってきても構いません。
単一のルート要素を持つカスタムコンポーネントで class
属性を使用すると、それらのクラスがこの要素に追加されます。この要素の既存のクラスは上書きされません。
例えば、このコンポーネントを宣言して:
const app = Vue.createApp({})
app.component('my-component', {
template: `<p class="foo bar">Hi!</p>`
})
2
3
4
5
使用するときにいくつかのクラスを追加したとします:
<div id="app">
<my-component class="baz boo"></my-component>
</div>
2
3
以下の HTML が描画されます:
<p class="foo bar baz boo">Hi</p>
クラスバインディングに対しても同様です:
<my-component :class="{ active: isActive }"></my-component>
isActive
が真と評価されるときは、以下の HTML が描画されます:
<p class="foo bar active">Hi</p>
コンポーネントに複数のルート要素がある場合、どのコンポーネントがこのクラスを受け取るかを定義する必要があります。これは $attrs
コンポーネントプロパティを使って行うことができます:
<div id="app">
<my-component class="baz"></my-component>
</div>
2
3
const app = Vue.createApp({})
app.component('my-component', {
template: `
<p :class="$attrs.class">Hi!</p>
<span>This is a child component</span>
`
})
2
3
4
5
6
7
8
コンポーネント属性の継承については、プロパティでない属性のセクションを参照してください。
# インラインスタイルのバインディング
# オブジェクト構文
:style
向けのオブジェクト構文は非常に簡単です。JavaScript オブジェクトということを除けば、ほとんど CSS のように見えます。CSS のプロパティ名には、キャメルケース (camelCase) またはケバブケース (kebab-case: クォートとともに使うことになります) のどちらでも使用することができます:
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data() {
return {
activeColor: 'red',
fontSize: 30
}
}
2
3
4
5
6
テンプレートをクリーンにするために、直接 style オブジェクトに束縛するのは、よいアイディアです:
<div :style="styleObject"></div>
data() {
return {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
}
2
3
4
5
6
7
8
ここでもまた、オブジェクト構文はしばしばオブジェクトを返す算出プロパティと併せて使用されます。
# 配列構文
:style
向けの配列構文は、同じ要素に複数のスタイルオブジェクトを適用することができます:
<div :style="[baseStyles, overridingStyles]"></div>
# 自動プリフィックス
:style
でベンダー接頭辞を要求される CSS プロパティを使用するとき、例えば、transform
においては、Vue.js は自動的に適切な接頭辞を検出し、適用されるスタイルに追加します。
# 複数の値
style プロパティに複数の (接頭辞付き) 値の配列を設定できます。例えば次のようになります:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
これは、配列内でブラウザがサポートしている最後の値だけを描画します。この例では、flexbox の接頭されていないバージョンをサポートしているブラウザでは display: flex
を描画します。