こんにちは、お読みいただきありがとうございます。 ケン(@gootablog)です。
仕事で管理画面を作る必要があり、初めてVuetifyを使いました。備忘録してどういうものを使ったか、UIコンポーネントを使ってみてどうだったかなどを書いていきます。
目次
version
@vue/cli@3.9.3
{
"name": "vuetify-sample",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^2.6.5",
"vue": "^2.6.10",
"vue-router": "^3.0.3",
"vuetify": "^2.0.14"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.11.0",
"@vue/cli-plugin-eslint": "^3.11.0",
"@vue/cli-service": "^3.11.0",
"@vue/eslint-config-prettier": "^5.0.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-vue": "^5.0.0",
"prettier": "^1.18.2",
"vue-template-compiler": "^2.6.10"
}
}
vuetifyとは
Vue Material Design Component Framework — Vuetify.js
- UIコンポーネント
- きれい
- ドキュメントが日本語翻訳されてる
- 201907にv2がリリースされた
vuetify install
基本的にここを見て自分にあった方法を行えば大丈夫
自分はvue-cliで追加しました
vue add vuetify
プラグイン用のファイル作成
※vue add vuetify
でインストールすると自動で設定をしてくれますが一応書きます。
ここに設定を書く。
今回は自動で必要なものを読み込む設定にする。 それプラスiconの読み込み
// src/plugins/vuetify.js
import Vue from "vue";
import Vuetify from "vuetify/lib";
Vue.use(Vuetify);
export default new Vuetify({
icons: {
iconfont: "mdi"
}
});
main.jsに書き込んで使えるようにする
設定を書いたファイルを読み込む
//...
import vuetify from "@/plugins/vuetify";
// ...
new Vue({
vuetify,
router,
render: h => h(App)
}).$mount("#app");
使用例
実際に使ったUIコンポーネントのサンプルをおいておきます。
サイト
https://vue-sample.kens-portfolio.com/vuetify
ソースコード
https://github.com/Kenj-I/vueSample
vuetifyを使うときはApp.vue
で大枠をv-app
タグで囲んでから使用しましょう。
テーブル
https://vue-sample.kens-portfolio.com/vuetify/table
<template>
<div>
<v-data-table
:headers="headers"
:items="listData"
:items-per-page="2"
:sort-by="'name'"
:sort-desc="true"
:footer-props="footerProps"
>
<template v-slot:item.column4="{ item }">
<span v-if="item.column4 === '444'">○</span>
<span v-else>X</span>
</template>
</v-data-table>
</div>
</template>
<script>
export default {
data: () => ({
loading: true,
headers: [
{ text: "Name", value: "name" },
{ text: "Column1", value: "column1" },
{ text: "Column2", value: "column2" },
{ text: "Column3", value: "column3" },
{ text: "Column4", value: "column4" }
],
footerProps: {
"items-per-page-options": [2, 4, 6]
},
listData: [
{
name: "AAA",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
},
{
name: "BBB",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
},
{
name: "CCC",
column1: "111",
column2: "222",
column3: "333",
column4: "555"
},
{
name: "DDD",
column1: "111",
column2: "222",
column3: "333",
column4: "555"
},
{
name: "EEE",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
},
{
name: "FFF",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
},
{
name: "GGG",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
},
{
name: "HHH",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
},
{
name: "III",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
},
{
name: "JJJ",
column1: "111",
column2: "222",
column3: "333",
column4: "444"
}
]
})
};
</script>
<style lang="scss" scoped>
div {
width: 800px;
margin: 0 auto;
}
</style>
こんな感じでv-data-table
タグに設定やデータを渡してあげると簡単にテーブルを表示することができます。
値を加工したい場合はtemplate
タグを使って加工する値のキーを指定してよしなにすることができます。
これだけでソートもできる、表示数も変えられる、ページネーションもできるって最高すぎます。
仕事ではサーバーサイドページネーションで作ったので表示数を変えたりソートしたりしたときは都度APIコールするようにして作成しました。
ダイアログ
https://vue-sample.kens-portfolio.com/vuetify/dialog
<template>
<v-layout>
<v-dialog v-model="dialog" :max-width="maxWidth">
<template v-slot:activator="{ on }">
<v-btn v-if="showBtn" class="btn" :color="btnColor" dark v-on="on">{{
btnText
}}</v-btn>
</template>
<v-card class="dialog">
<v-card-title>
<span class="dialog-title"> {{ dialogTitle }}</span>
</v-card-title>
<v-card-text>
<span class="dialog-text">
{{ dialogText }}
</span>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn class="btn" :color="cancelColor" @click="cancel">
{{ cancelText }}
</v-btn>
<v-btn class="btn" :color="executeColor" @click="execute">
{{ executeText }}
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-layout>
</template>
<script>
export default {
props: {
showBtn: {
type: Boolean,
default: true
},
btnText: {
type: String
},
btnColor: {
type: String,
default: "#4BB9C0"
},
maxWidth: {
type: Number,
default: 500
},
cancelColor: {
type: String,
default: "#D53476"
},
executeColor: {
type: String,
default: "#4BB9C0"
},
cancelText: {
type: String,
default: "Disagree"
},
executeText: {
type: String,
default: "Agree"
},
dialogTitle: {
type: String,
required: true
},
dialogText: {
type: String,
default: ""
}
},
data: () => ({
dialog: false
}),
methods: {
execute() {
this.close();
this.$emit("execute");
},
cancel() {
this.close();
this.$emit("cancel");
},
open() {
this.dialog = true;
},
close() {
this.dialog = false;
}
}
};
</script>
<style lang="scss" scoped>
.btn {
display: block;
color: white !important;
}
</style>
データを削除したり、更新するとき、ステータスを変えるときに使用しました。
ダイアログのレイアウトはいろいろと設定ができるのでサイズやカラーなどサイトに合うようにカスタマイズできます。
表示されるときは親コンポーネントでrefs
を使って子コンポーネントのmethodsを実行して表示するようにしています。そしてダイアログで確認後の実行アクションはemit
を使い親コンポーネントに知らせています。
アラート
https://vue-sample.kens-portfolio.com/vuetify/alert
<template>
<transition>
<div v-if="show" class="alert">
<v-alert v-if="type" v-model="show" :type="type" outlined dense>{{
message
}}</v-alert>
</div>
</transition>
</template>
<script>
export default {
props: {
show: {
type: Boolean,
default: false
},
type: {
type: String,
default: ""
},
message: {
type: String,
default: ""
}
}
};
</script>
<style lang="scss" scoped>
.alert {
box-shadow: 0px 0px 5px rgba(#000, 0.1);
position: fixed;
top: 10px;
right: 5px;
>>> .v-alert {
margin: 0;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
}
}
.v-enter-active,
.v-leave-active {
transition: all 0.5s;
}
.v-enter,
.v-leave-to {
right: -100px;
opacity: 0;
}
</style>
APIを実行したときなどの結果をアラートを使って表示させました。
右上から出てきて数秒後に消すという感じにしています。実際にはVuexで状態管理をしました。
現状複数のアラートを出すと書き換わってしまうので、複数出せるようにしたいところ。
ローディング
https://vue-sample.kens-portfolio.com/vuetify/loading
<template>
<div v-if="loading" class="progress-bar">
<v-progress-linear
:indeterminate="true"
:fixed="true"
color="#5252D0"
></v-progress-linear>
<div class="fullview" v-if="fullView"></div>
</div>
</template>
<script>
export default {
props: {
loading: {
type: Boolean,
required: true
},
fullView: {
type: Boolean,
required: true
}
}
};
</script>
<style lang="scss" scoped>
.fullview {
width: 100%;
height: 100vh;
background-color: #f5f7fc;
position: fixed;
top: 0;
left: 0;
z-index: 50;
opacity: 0.5;
}
.progress-bar {
width: 100%;
height: auto;
box-shadow: 0px 0px 5px rgba(#000, 0.1);
position: fixed;
top: 0;
left: 0;
z-index: 100;
}
</style>
ローディングはいくつかパターンがありましたが、プログレスバーを使用しました。非同期で送るのでしっかりリクエストを送ってるのはわかるようにしてます。
ローディングをしているときは、レイヤーを一枚挟んでクリックなどの操作をしないようにしています。
UIコンポーネントを使ってみて
大きめのUIコンポーネントを使ったのはこの4つくらいでした。これくらいで基本的な管理のページを作れるのはいいですね。レイアウト(flexやmarginなど)もタグに設定を書き足せばいいだけなのでとても便利でした。
ただこれまでBootstrapなどのCSSフレームワークを使ってこず、基本はフルスクラッチみたいな感じでやってきました。初めて使ってみて、使い方を理解するまでは少し難しさを感じましたが慣れるとサクサク書けます。ポイントポイントで使うととても強力なツールになりそうです。
今後も機会があったら積極的につかってみようと思います。