Vuetify は Vue.js で多く使われている UI コンポーネントです。現在のバージョンは Vue 3 には対応していません。
現在 Vue 3 に対応する Alpha 版の Vuetify 3 が公開されています。開発スケジュールは以下のとおりになっています。
リリース目標: 2022年2月 アルファ: 2021年 3月 ベータ: 2021年12月
まだ Alpha 版で安定しないバージョンではありますが Vuetify 3 でどのような機能が追加されるんか見ていきましょう。
インストール
vue-cli
vue-cli 4.0 を利用してプロジェクトを作成します。
vue create my-appVue 3 を選択します。
? Please pick a preset:
Default ([Vue 2] babel, eslint)
❯ Default (Vue 3) ([Vue 3] babel, eslint)
Manually select features Vuetify をプロジェクトに追加します。
cd my-vue-app/
vue add vuetifyVuetify 3 Preview (Vuetify 3) を選択します。
? Choose a preset: (Use arrow keys)
Configure (advanced)
Default (recommended)
Vite Preview (Vuetify 3 + Vite)
Prototype (rapid development)
> Vuetify 3 Preview (Vuetify 3)Vite
Vuetify 3 は Vite でも使用することでできます。まずは Vite のドキュメントにある手順のとおりにプロジェクトを作成します。
# npm 6.x
npm init vite@latest my-vue-app --template vue
# npm 7+ は追加で 2 つのダッシュが必要:
npm init vite@latest my-vue-app -- --template vue
# yarn
yarn create vite my-vue-app --template vue
# pnpm
pnpm create vite my-vue-app -- --template vueVuetify をプロジェクトに追加します。
cd my-vue-app/
vue add vuetifyVite Preview (Vuetify 3 + Vite) を選択します。
? Choose a preset: (Use arrow keys)
Configure (advanced)
Default (recommended)
Vite Preview (Vuetify 3 + Vite)
Prototype (rapid development)
> Vuetify 3 Preview (Vuetify 3)Vuetify の初期化
Vuetify 2 までは new Vuetify() のように Vuetify インスタンスを生成していましたが Vuetify 3 からは Vue 3 の createApp のように createVuetify をインポートして Vuetify インスタンスを生成します。
(Vue 3 と同じく tree shaking を効かせるためかと思います)
- Vuetify 2
// src/main.ts
import Vue from 'vue'
import Vuetify from 'vuetify'
const vuetify = new Vuetify({})
Vue.use(vuetify)
new Vue({
vuetify,
}).$mount('#app')- Vuetify 3
// src/main.ts
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createApp } from 'vue'
import App from './App.vue'
import { createVuetify } from 'vuetify'
const vuetify = createVuetify({})
createApp(App)
.use(vuetify)
.mount('#app')デフォルト Prop
Vuetify のインスタンスを生成する際にオプションとしてあるコンポーネントに対してデフォルトの Props を設定できるようになりました。
例えば、以下のようにボタンに対するデフォルトの props を設定できます。
// src/plugins/vuetify.js
import { createVuetify } from "vuetify";
export default createVuetify({
defaults: {
VBtn: {
flat: true,
disabled: true,
},
},
});以下のように props を指定しないで <v-btn> を配置しても、デフォルト Prop が適用されています。
<template>
<v-app class="app">
<div class="flex ma-2">
<v-btn>Button</v-btn>
</div>
</v-app>
</template>
Props は以下の優先度で適用されます。
- コンポーネントに直接渡された Props
defaultsで設定した Props- Vuetify のデフォルトの Props
Defaults providers
<v-defaults-provider> コンポーネントを利用すると Default providers 配下のコンポーネントにのみ上書きして defaults の設定を適用できます。
<template>
<v-app class="app">
<div class="flex ma-2">
<v-btn>Button</v-btn>
<v-defaults-provider :defaults="defaults">
<v-btn>Button inside providers </v-btn>
</v-defaults-provider>
</div>
</v-app>
</template>
<script setup>
const defaults = {
VBtn: {
color: "secondary",
disabled: false,
},
};
</script>
テーマ
カスタムテーマ
Vuetify の提供する ligth と dark のテーマに加えてカスタムのテーマを設定できるようになりました。(それに伴い theme の isDark プロパティは削除されました)
使用するテーマは defaultTheme プロパティで設定できます。
// src/plugins/vuetify.ts
import { createVuetify, ThemeDefinition } from "vuetify";
const myCustomTheme: ThemeDefinition = {
dark: false,
colors: {
background: '#FFFFFF',
surface: '#FFFFFF',
primary: '#FF7043',
error: '#B00020',
info: '#2196F3',
success: '#4CAF50',
warning: '#FB8C00',
}
}
export default createVuetify({
theme: {
defaultTheme: 'myCustomTheme',
themes: {
myCustomTheme
}
}
});テーマの変更
ユーザーが動的にアプリケーションのテーマを切り替えることができるようにするためには <v-app> に theme props を渡すことで切り替えることができます。
<template>
<v-app :theme="theme">
<v-container class="px-0" fluid>
<v-radio-group v-model="theme">
<v-radio color="primary" label="Light Theme" value="light" />
<v-radio color="primary" label="Dark Theme" value="dark" />
<v-radio color="primary" label="My Custom Theme" value="myCustomTheme" />
</v-radio-group>
</v-container>
</v-app>
</template>
<script setup>
import { ref } from "vue";
const theme = ref("light");
</script>
Theme providers
<v-theme-provider> コンポーネントは配下のコンポーネントのみにテーマを適用できます。
デフォルトでは <v-theme-provider> 内では背景色は元のテーマのままとなります。背景色にもテーマを適用させるには、with-background props を渡します。
<template>
<v-app>
<v-theme-provider theme="dark">
<div class="pa-10">
<v-card title="Title" subtitle="Subtitle"></v-card>
</div>
</v-theme-provider>
<v-theme-provider theme="light">
<div class="pa-10">
<v-card title="Title" subtitle="Subtitle"></v-card>
</div>
</v-theme-provider>
<v-theme-provider theme="dark" with-background>
<div class="pa-10">
<v-card title="Title" subtitle="Subtitle"></v-card>
</div>
</v-theme-provider>
</v-app>
</template>
コンポーネント単位のテーマ
Vuetify 2 ではコンポーネント単位でダークテーマを適用させたい場合には dark props を渡して設定していました。
- Vuetify 2
<template>
<v-app>
<v-container>
<v-card dark>
<v-card-title>card title</v-card-title>
</v-card>
</v-container>
</v-app>
</template>Vuetify 3 では前述のとおり light と dark 以外のテーマも設定できるので代わりに theme props で設定します。
<template>
<v-app>
<v-container>
<v-card theme="dark">
<v-card-title>card title</v-card-title>
</v-card>
</v-container>
</v-app>
</template>
ブレークポイント
Vuetify 2 では JavaScript から現在のブレークポイントにアクセスするために this.$vuetify.breakpoints からアクセスできました。例えば現在の画面サイズが sm 以下の場合にのみ実行したい場合には以下のようにします。
- Vuetify 2
<template>
<v-app>
<h1>{{screenName}}</h1>
</v-app>
</template>
export default {
computed: {
screenName() {
if (this.$vuetify.breakpoints.smAndDown) {
return 'mobile'
} else {
return 'desktop'
}
}
}
}Vuetify 3 では useDisplay() 関数により現在のブレークポイントを取得できます。useDisplay() の返り値は ref でラップされているのでリアクティブ変数です。
- Vuetify 3
<template>
<v-app>
<h1>{{ screenName }}</h1>
</v-app>
</template>
<script setup>
import { computed } from "vue";
import { useDisplay } from "vuetify";
const display = useDisplay();
const screenName = computed(() => {
if (display.smAndDown.value) {
return "mobile";
} else {
return "desktop";
}
});
</script>プラットフォーム
useDisplay() から新たにユーザーエージェントの情報を取得できるようになりました。
platform: {
android: boolean
ios: boolean
cordova: boolean
electron: boolean
chrome: boolean
edge: boolean
firefox: boolean
opera: boolean
win: boolean
mac: boolean
linux: boolean
touch: boolean
ssr: boolean
}<script setup>
import { useDisplay } from "vuetify";
const display = useDisplay()
if (display.platform.value.chrome) {
console.log('I am chrome')
} else if (display.platform.value.firefox) {
console.log('I am firefox')
} else if (display.platform.value.edge) {
console.log('I am edge')
}
</script>カード
新しいコンポーネントがいっぱい増えています。が、詳細は不明です。
- v-card-avatar
- v-card-header
- v-card-header-text
- v-card-img
- v-card-media
イメージ
<v-img> の contain props は削除されデフォルトで contain が挙動となるようになりました。Vuetify 2 までの挙動を維持するために新たに cover props が追加されました。
つまり、以下の 2 つのコードは同等のものとなります。
- Vuetify 2
<template>
<v-img src="/images/sample.png" contain />
</template>- Vuetify 3
<template>
<v-img src="/images/sample.png" />
</template>Vuetify 2 では画像の表示するため <div> タグに background-image を指定していましたが Vuetify 3 からは <img> タグを使用するようになりました。
ボタン
サイズ
以下のサイズを決定する props は削除され、代わりに size プロパティで指定するようになりました。
-
x-small -
small -
large -
x-large -
Vuetify 2
<template>
<v-app class="app">
<div class="flex flex-column">
<v-btn color="primary" class="mx-2" x-small>Extra Small Button</v-btn>
<v-btn color="primary" class="mx-2" small>Small Button</v-btn>
<v-btn color="primary" class="mx-2">Default Button</v-btn>
<v-btn color="primary" class="mx-2" large>Large Button</v-btn>
<v-btn color="primary" class="mx-2" x-large>Extra Large Button</v-btn>
</div>
</v-app>
</template>- Vuetify 3
<template>
<v-app class="app">
<div class="flex flex-column">
<v-btn color="primary" class="mx-2" size="x-small">Extra Small Button</v-btn>
<v-btn color="primary" class="mx-2" size="small">Small Button</v-btn>
<v-btn color="primary" class="mx-2" size="default">Default Button</v-btn>
<v-btn color="primary" class="mx-2" size="large">Large Button</v-btn>
<v-btn color="primary" class="mx-2" size="x-large"
>Extra Large Button</v-btn
>
</div>
</v-app>
</template>
variant
以下の props は廃止され代わりに variant で指定するようになりました。
textoutlinedplain
variant には以下を設定できます。
-
'contained'
-
'outlined'
-
'plain'
-
'text'
-
'contained-text'
-
Vuetify 2
<template>
<v-app>
<v-container>
<v-btn color="primary" text>text button</v-btn>
<v-btn color="primary" outlined>outlined button</v-btn>
<v-btn color="primary" plain>outlined button</v-btn>
</v-container>
</v-app>
</template>- Vuetify 3
<template>
<v-app>
<v-container>
<v-btn color="primary" variant="outlined">outlined button</v-btn>
<v-btn color="primary" variant="text">text button</v-btn>
<v-btn color="primary" variant="plain">plain button</v-btn>
<v-btn color="primary" variant="contained">contained button</v-btn>
<v-btn color="primary" variant="contained-text">contained-text button</v-btn>
</v-container>
</v-app>
</template>
depressed は廃止され代わりに flat となりました。
stacked プロパティが追加されました。(詳細は不明)
<template>
<v-app>
<v-container>
<v-btn color="primary" stacked>stacked button</v-btn>
<v-btn color="primary" flat>flat button</v-btn>
</v-container>
</v-app>
</template>
No SSR
<v-no-ssr> コンポーネント配下はサーバーサイドでは実行されなくなります。
共通 Props?
いろんなコンポーネントに position props を渡せるようになったようです。
- interface
export interface PositionProps {
absolute?: boolean
bottom?: boolean | number | string
fixed?: boolean
left?: boolean | number | string
position?: Position
right?: boolean | number | string
top?: boolean | number | string
}<template>
<v-app>
<v-container>
<v-btn absolute top="100">button</v-btn>
<v-card
absolute
top="0"
left="200"
title="title"
subtitle="subtitle"
></v-card>
</v-container>
</v-app>
</template>
position 以外にも以下の props はコンポーネントの共通の props と定義されているっぽい?
densityheightmaxHeightmaxWidthminHeightminWidthwidththemetagelevationborderrounded
v-intersect
v-intersect ディレクティブの引数の順番が変わり isIntersecting が初めの引数になりました。
v-kbd
kbdをラップしたコンポーネント?
<template>
<v-app>
<v-container>
<v-kbd>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorum, magnam
repudiandae. Porro dolorum quo nesciunt laboriosam minus voluptate,
reiciendis quibusdam necessitatibus debitis rerum cum inventore.
Necessitatibus nostrum quo minima quia?
</v-kbd>
</v-container>
</v-app>
</template>


