お題
表題のお試し。前回作成したプロジェクトをベースに、Vuetifyの各種UIコンポーネントを試していく。
今回は、create-nuxt-appで作成した時点のデフォルトレイアウトで使われているUIコンポーネントを掘り下げていく。
それ以外のUIコンポーネントについては次回以降で。
対象読者
Linux(ubuntu)環境を開発用の端末に使っていて、これからNuxt.js
とVuetify
を組み合わせて使ってみようと思っている人。
Linux(ubuntu)環境でVue.js/Nuxt.js試行Index
開発環境
# OS
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
# 依存モジュールのバージョン
package.json
の内容より、以下の通り。
"nuxt": "^2.0.0",
"vuetify": "^1.2.4",
実践
create-nuxt-appで作成した時点のデフォルトレイアウト
プロジェクト作成時点のディレクトリ構造は下記(今回の説明に必要な部分のみ抜粋)
try001/
〜〜【省略】〜〜
├── components
│ ├── Logo.vue
│ ├── README.md
│ └── VuetifyLogo.vue
├── layouts
│ ├── README.md
│ └── default.vue
〜〜【省略】〜〜
├── pages
│ ├── README.md
│ ├── index.vue
│ └── inspire.vue
〜〜【省略】〜〜
プロジェクト作成時点の layouts/default.vue
解析
layouts/default.vue
<template>
<v-app dark>
〜〜【1:ナビゲーション・ドロワー】〜〜
〜〜【2:ツールバー】〜〜
〜〜【3:コンテンツ】〜〜
〜〜【4:ナビゲーション・ドロワー(右)】〜〜
〜〜【5:フッター】〜〜
</v-app>
</template>
<script>
export default {
data() {
return {
〜〜省略〜〜
}
}
}
</script>
実際の表示
各ブロックを見ていく前に <v-app>
を少しいじる。
デフォルトでは、 <v-app dark>
であり、 dark
属性によりダークテーマが採用されている。
まずは単純にこの属性をなくしてみると、こうなる。
で、 <v-app>
には light
属性というのがあるようなので、指定してみる。 <v-app light>
あれっ、属性なしの <v-app>
と変わらないな。
【1:ナビゲーション・ドロワー】
参考:https://vuetifyjs.com/en/components/navigation-drawers
開閉用のコンポーネント。デフォルトでは【2:ツールバー】にあるボタン押下で開閉するよう制御されている。
<v-navigation-drawer
:mini-variant="miniVariant"
:clipped="clipped"
v-model="drawer"
fixed
app
>
〜〜【スロットコンテンツ】〜〜
</v-navigation-drawer>
指定されている属性群を全て取っ払って、<v-navigation-drawer>
だけにしてみると、こうなる。
【2:ツールバー】の上に重なってしまっているし、高さも画面下部に届いていない。↓
↑に対し、デフォルトで使われていた属性を1つ1つ追加してみる。
★PROPS「fixed
」
fixed
は「要素を固定します」とのこと。とりあえず追加してみる。
<v-navigation-drawer
fixed
>
お、画面下部まで伸びた。
★PROPS「app
」
app
は「アプリケーションレイアウトの一部としてコンポーネントを指定します。動的にコンテンツのサイズを調整するために使用されます」とのこと。
<v-navigation-drawer
fixed
app
>
【2:ツールバー】の上に重ならなくなった。
★「v-model
」
次は、ドロワーの動き(ツールバーにあるボタン押下による開閉)の制御に使われているv-model
を追加。
これがないと(厳密には、これとツールバーにあるボタンに付けられたクリックイベント)ドロワーが開閉しない。
<v-navigation-drawer
v-model="drawer"
fixed
app
>
★PROPS「clipped
」
clipped
は「クリップされたドロワーはアプリケーションツールバーの下にある」とのこと。。。
う〜ん? 使用事例も載っていないし・・・。
<v-navigation-drawer
:clipped="clipped"
v-model="drawer"
fixed
app
>
↑で指定されている「:clipped="clipped"
」の左辺の「:
」は「v-on:
」の略でイベントを拾う。
「clipped
」かどうかを右辺の「"clipped"
」変数(イベントと同じ変数名にしてるからややこしいのか?)から判断。つまり、boolean
値。
これは下記のように初期化されている。
<script>
export default {
data() {
return {
clipped: false,
〜省略〜
}
}
}
</script>
この clipped
のフラグ切り替えを【2:ツールバー】が担っている様子。
よって、挙動の解析は後述。
★PROPS「mini-variant
」
mini-variant
は「ナビゲーションドロワーの幅を縮小し、.sync修飾子も受け入れます。これをクリックすると、引き出しが再び開きます。」とのこと。
デフォルト事例では「.sync
」は付いていない。単純に幅が縮小される?
<v-navigation-drawer
:mini-variant="miniVariant"
:clipped="clipped"
v-model="drawer"
fixed
app
>
↑で指定されている「:mini-variant="miniVariant"
」についてはclipped
の説明と同様で、
boolean
値のminiVariant
変数から判断。
これは下記のように初期化されている。
<script>
export default {
data() {
return {
〜省略〜
miniVariant: false,
〜省略〜
}
}
}
</script>
この miniVariant
のフラグ切り替えもやはり【2:ツールバー】が担っている様子。
よって、これも、挙動の解析は後述。
ちなみに、「.sync
」を使った事例は下記に載っていた。
https://vuetifyjs.com/en/components/navigation-drawers#mini
【スロットコンテンツ】
Vue.jsにおけるスロットコンテンツ自体については下記参照。
https://jp.vuejs.org/v2/guide/components-slots.html
<my-component>
<slot></slot>
</my-component>
という形でコンポーネント定義しておくと、呼び出し側で
<my-component>
<div>ABCDE</div>
</my-component>
というようにタグ(別コンポーネントも可)が入れられるようになるもの。
さて、デフォルトレイアウトにおける<v-navigation-drawer>
のスロットコンテンツとしては下記が定義されている。
<v-list>
<v-list-tile
v-for="(item, i) in items"
:to="item.to"
:key="i"
router
exact
>
<v-list-tile-action>
<v-icon v-html="item.icon" />
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-text="item.title" />
</v-list-tile-content>
</v-list-tile>
</v-list>
items
の内容をループ表示している。
items
の内容は下記。
items: [
{ icon: 'apps', title: 'Welcome', to: '/' },
{ icon: 'bubble_chart', title: 'Inspire', to: '/inspire' }
],
Material Design Icons
上記で items
に使われている icon: 'apps'
と icon: 'bubble_chart'
は下記で用意されているものからピックアップされている。
https://material.io/tools/icons/?icon=terrain&style=baseline
icon
属性については下記参照。
https://vuetifyjs.com/ja/components/icons
【2:ツールバー】
参考: https://vuetifyjs.com/ja/components/toolbars
サイトナビゲーションとして使われる。前述のナビゲーションドロワーと連携した使い方も有用。
<v-toolbar
:clipped-left="clipped"
fixed
app
>
<v-toolbar-side-icon @click="drawer = !drawer" />
<v-btn
icon
@click.stop="miniVariant = !miniVariant"
>
<v-icon v-html="miniVariant ? 'chevron_right' : 'chevron_left'" />
</v-btn>
<v-btn
icon
@click.stop="clipped = !clipped"
>
<v-icon>web</v-icon>
</v-btn>
〜〜【以降、省略】〜〜
</v-toolbar>
fixed
とapp
は前述の通りなので省略。
:clipped-left="clipped"
前述した通りだけど、【1:ナビゲーション・ドロワー】は:clipped="clipped"
とあり、clipped
のオンオフで制御されるようになっている。
これが、【2:ツールバー】が持つ:clipped-left="clipped"
と、どう絡むのか? やってみる。
"clipped"
のオンオフ切り替えは↓
<v-btn
icon
@click.stop="clipped = !clipped"
>
<v-icon>web</v-icon>
</v-btn>
覆い被さるとはちょっと違うかな。こういうのをクリップされたと言う?
:mini-variant="miniVariant"
前述した通りだけど、【1:ナビゲーション・ドロワー】は:mini-variant="miniVariant"
とあり、miniVariant
のオンオフで制御されるようになっている。
これが、【2:ツールバー】に含まれるボタンによるオンオフ切り替え(↓)と、どう絡むのか? やってみる。
"clipped"
のオンオフ切り替えは↓
<v-btn
icon
@click.stop="miniVariant = !miniVariant"
>
<v-icon v-html="miniVariant ? 'chevron_right' : 'chevron_left'" />
</v-btn>
なるほど。幅が縮小された!
【3:コンテンツ】
コンテンツは下記の通り、ページコンポーネント(/pages
配下のvueファイル)を読み込むだけ。
参考: https://ja.nuxtjs.org/api/components-nuxt/
<v-content>
<v-container>
<nuxt />
</v-container>
</v-content>
/pages
直下にはindex.vue
が存在する。中身は↓(一部省略)
<template>
<v-layout
〜省略〜
>
<v-flex
〜省略〜
>
<div class="text-xs-center">
<logo/>
<vuetify-logo/>
</div>
<v-card>
〜省略〜
</v-card>
</v-flex>
</v-layout>
</template>
ちょうど↑で表現されるビューが↓
<v-card>
要素配下は次回以降、掘り下げていこう。
<logo/>
と<vuetify-logo/>
はコンポーネント。
以下のようにインポートしている。
<script>
import Logo from '~/components/Logo.vue'
import VuetifyLogo from '~/components/VuetifyLogo.vue'
export default {
components: {
Logo,
VuetifyLogo
}
}
</script>
【4:ナビゲーション・ドロワー(右)】
使われているPROPSには違うものがあるもののナビゲーションドロワーは説明済みなので省略。
【5:フッター】
参考: https://vuetifyjs.com/en/components/footer
ユーザーがサイト内の任意のページからアクセスしたいと思う可能性がある一般的な情報を表示するために使用される。
<v-footer
:fixed="fixed"
app
>
<span>© 2017</span>
</v-footer>
ここはあえて説明なしでもいいかな。
まとめ
デフォルトのレイアウトだけでも、ふんだんに Vuetify の UIコンポーネントが活用されている。
次回は、まっさらな状態から、各種UIコンポーネントを少しずつ使い倒してみよう。