Vue.jsで楽に綺麗にコンポーネントを作れるVuetifyフレームワークですが、楽だからこそ「さらに発展させてこうしたい!(もうちょい頑張ったらCSS書かずに済みそう...)」という時にちょっと悩みます。
なので、悩んだところをちょこちょこメモ書き&自学のために残します。誰かのお役に立てば幸いです。
フロント修行中ですので、ご指摘大歓迎です。
やりたいこと
- 配列型の中にある各文字列をボタンの表示に利用したい
- ボタンを押したら、選択されたボタンの色が変わって欲しい
- 押されたボタンのキー(配列内の文字列)を取得したい
実装例
<v-btn
v-for="(item, index) of items"
:key="item"
:color="selectedTemplate && index === selectedIndex ? 'warning' : null"
@click="
selectedTemplate = item;
selectedIndex = index;
"
>
{{ item }}
</v-btn>
<script>
// Vueインスタンス内の必要部分から抜粋
data: {
items: [
"A",
"B",
"C"
],
selectedItem: null
}
// 以下略
</script>
解説
1. 配列型の中にある各文字列をボタンの表示に利用したい
script内の
data
で配列データitems
を定義-
template内の
v-for="(item, index) of items"
で配列データをforで回す- 配列内の要素
item
と要素のインデックスindex
を取得する -
{{ item }}
で要素を表示する -
:key="index"
はv-for
を使う上で必要と怒られるから入れる(今回利用しないので"item"
でもOK)
- 配列内の要素
2. ボタンを押したら、選択されたボタンの色が変わって欲しい
- script内の
data
で選択されたボタン(ここではselectedItem
)の初期状態を定義
設定しないとエラーになります。
selectedIndex
については、下で説明する演算子( :color="selectedItem && index === selectedIndex ? 'warning' : null"
)の中でアクセスする際には必ず値が入っている(右辺が真の場合は値がある)のでエラーが出ない。右辺と左辺を入れ替えるとエラーが出るので、 selectedIndex
も定義しておくほうが無難...。
-
template
v-btn
内の@click=
でクリックイベントを用意- クリックイベント内
selectedItem = item;
でそのボタンの要素をselectedItem
変数に入れる -
selectedIndex = index;
でその要素のインデックスをselectedIndex
変数に入れる
- クリックイベント内
-
v-btn
要素が持っている属性color
にv-bind
で三項演算子を入れる:color="selectedItem && index === selectedIndex ? 'warning' : null"
- もし何かしらのボタンが押されており、かつその選択されたアイテムのインデックスがこのボタン要素のインデックスと同一なら、色を
warning
系にする、それ以外は色つけしない
3. 押されたボタンのキー(配列内の文字列)を取得したい
-
script
内でthis.selectedItem
に値が入る(取得タイミングには注意!押されなければnull
のまま)
余談
v-for
いろいろ
配列型
-
v-for="item in items"
→ 配列内の要素そのものだけ取る -
v-for="(item, index) in items
→ 上で使ったやつ。インデックスが取れる
辞書型
-
v-for="item in objectItems
→ 辞書データ内の値部分だけ取る -
v-for="(item, name) in objectItems
→ 辞書データ内の値部分(item
)とキー部分(name
)を取る- 値が先なので注意
-
v-for="(item, name, index) in objectItems
→ もうわかる
v-btn
に block
属性を追加すると、ボタンの一つ一つが横の幅を全て取るので、ボタンが縦に並ぶ
イメージとしては、select
で選べるオプション要素が常に開いているような、よくあるデザインで表示できる!
<v-btn
block
v-for="(item, index) of items"
:key="item"
:color="selectedTemplate && index === selectedIndex ? 'warning' : null"
@click="
selectedTemplate = item;
selectedIndex = index;
"
>
{{ item }}
</v-btn>
色を選ぶ際の三項演算子は、Boolean型のデータだともっとシンプルになる
- 例えば「選択されていないボタンは
text
属性で背景をなくす」なら、下のような式になる:text="!selectedItem || index !== selectedIndex"
演算を長くしたかったので無理やり上記のような式にしましたが、この式は厳密にはよくないです。右辺が真の場合は左辺も必ず真なので、 !selectedItem ||
は不要と言えるからです。ただし、右辺をなくす場合は data
で selectedIndex
を定義してやらなければエラーが出ます(右辺が偽の場合は必ず selectedIndex
に値があるため、上の式ではエラーにならない)。ちなみに右辺だけだと選択したボタンも背景が消えますので判定式の意味がなくなる。
warning
系のカラー?
マテリアルデザインではおなじみのsuccessやerrorなどアラート用要素に、既に組み込みクラスとしての色の組み合わせが用意されています。
Vuetifyでは、success, info, warning, errorの四つのタイプが用意されているようです。
もちろん、他の色のクラスも利用できます。