Vuetify 3 Alpha の主な変更点
[Vuetify](https://vuetifyjs.com/) は Vue.js で多く使われている UI コンポーネントです。現在のバージョンは Vue 3 には対応していません。 現在 Vue 3 に対応する Alpha 版の Vuetify 3 が公開されています。開発スケジュールは以下のとおりになっています。
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-app
Vue 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 vuetify
Vuetify 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 vue
Vuetify をプロジェクトに追加します。
cd my-vue-app/
vue add vuetify
Vite 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 providres
<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-colmun">
<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-colmun">
<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
で指定するようになりました。
text
outlined
plain
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 と定義されているっぽい?
density
height
maxHeight
maxWidth
minHeight
minWidth
width
theme
tag
elevation
border
rounded
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>