やりたいこと
Vuetifyのボタンコンポーネントである、v-btn
を画面サイズでlargeにしたりsmallにしたり変えたい
<v-btn color="primary">ボタン</v-btn>
結論
結論から言うと下記のようになります。
<v-btn color="primary" v-bind="size">ボタン</v-btn>
size () {
const btnSize = {xs:'x-small',sm:'small',lg:'large',xl:'x-large'}
const size = btnSize[this.$vuetify.breakpoint.name];
return size ? { [size]: true } : {}
}
まずは、Vuetify
のブレークポイント(xs
やlg
等)がキーにして、そのキーの値として、v-btnのサイズを指定してあげます。
this.$vuetify.breakpoint.name
は現在の画面サイズの名前が取れるので、オブジェクトへのアクセスをします。
md
の場合は何も指定しなくて良いので、それ以外の場合はx-small:true
のようにpropsで指定できる形で返します。
以下TSでの詳細になります。
やりかた
1
まずはv-btnが受け取れるサイズを確認します。
以下がpropsで指定できます。mdの場合は何も指定しないようです。
- x-small
- small
- large
- x-large
この情報から型を作成します。
type ButtonSize = 'x-small' | 'small' | 'large' | 'x-large';
propsで指定できるもののユニオン型ができました。
2
Vuetifyに定義されているブレークポイントの名称をインポートします。
import { BreakpointName } from "vuetify/types/services/breakpoint"
// BreakpointNameは"xs" | "sm" | "md" | "lg" | "xl"のようなユニオン型です。
結論で書いたように必要なのは
{xs:'x-small',sm:'small',lg:'large',xl:'x-large'}
のような、
Vuetify
のブレークポイント(xs
やlg
等)がキーに、値としてv-btnのサイズのようなオブジェクトの型が必要です。
これを実現するには、mapped typeを使用します。
これを利用すると下記のようにできます。
import { BreakpointName } from "vuetify/types/services/breakpoint"
type ButtonSize = 'x-small' | 'small' | 'large' | 'x-large';
type ResponsiveButton = {
[Key in BreakpointName]: ButtonSize
}
しかし、ここで問題があります。
BreakpointNameは"xs" | "sm" | "md" | "lg" | "xl"のようなユニオン型です。
ボタンのサイズはmdがないので、BreakpointNameから減らすか、ButtonSizeにダミー的な値を追加する必要があります。
ここではBreakpointNameから減らします。
Exclude
を使用すると指定の型から対象を除いた型を作成できます。
import { BreakpointName } from "vuetify/types/services/breakpoint"
type ButtonSize = 'x-small' | 'small' | 'large' | 'x-large';
type ResponsiveButton = {
[Key in Exclude<BreakpointName,'md'>]: ButtonSize
}
3
あとは先程のメソッドを作成します。
$vuetify.breakpoint.name
でmd
が取得できてしまうのでその点だけ処理を追加しています。
size () {
if (this.$vuetify.breakpoint.name === 'md') {
return {};
}
const btnSize:ResponsiveButton = {xs:'x-small',sm:'small',lg:'large',xl:'x-large'}
const size = btnSize[this.$vuetify.breakpoint.name];
return { [size]: true }
}