はじめに
前回の続きの記事となります。
今回からVuetifyでレスポンシブなヘッダーを作成していきます。
本記事では、サイドメニューとハンバーガーメニューの作成まで行います。
完成イメージは下記の通りです。
本記事の内容
■ App.vueファイルの初期化
■ ヘッダーのタイトル作成方法
■ ヘッダーのハンバーガーメニュー作成方法
■ ヘッダーのサイドメニュー作成方法
Contents
App.vueファイルの初期化
作業内容
① App.vueの内容をクリア
② コンポーネントの3つのタグ(template
・script
・style
)を追加
③ templateタグ内にv-app
タグを追加
まず、デフォルトでApp.vueにいろいろと書かれていると思いますが、すべて消して以下のようにコーディングしてください。
そして、今回ほぼすべてのコンポーネントに対し、Vuetifyを使用するため、v-app
タグで囲ってください。
v-app
タグの正体ですが、こちらはVuetifyのコンポーネントとなります。
以降でもv-
で始まるタグがたびたび出現しますが、これらはすべてVuetifyのコンポーネントです。
なお、v-app
タグはid=app
をデフォルトで含むため、記載する必要はありません。(記載してもエラーにはなりません。)
1 2 3 4 5 6 7 8 9 10 |
<template> <v-app> <!-- ここにヘッダーをコーディング --> </v-app> </template> <script> </script> <style></style> |
また、補足ですが、templateタグ直下には複数の子要素を置くことができません。
templateタグ直下でなければ、通常通り子要素を置くことができます。
1 2 3 4 5 |
<template> <v-app> <header></header> </v-app> </template> |
1 2 3 4 5 |
<template> <v-app> </v-app> <header></header> </template> |
以下が今回のポイントとなります。
■ Vuetifyのコンポーネントは必ずv-app
タグで囲む必要がある。
■ Vuetifyのコンポーネントは必ずv-
から始まる。
■ v-app
タグにはid=app
が含まれている。
■ template
タグ直下には子要素は必ずひとつだけ。
ヘッダーのタイトル作成方法
次に下図のようなヘッダーのタイトルを表示させます。
作業内容
① header
タグ追加
② v-app-bar
タグ追加(appディレクティブとdarkディレクティブ指定)
③ v-toolbar-title
タグ追加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<template> <v-app> <!-- ここから追加 --> <header> <v-app-bar app dark > <v-toolbar-title>MyPortfolioSite</v-toolbar-title> </v-app-bar> </header> <!-- ここまで追加 --> </v-app> </template> |
headerタグ追加
ヘッダー部分はHTML5から追加されたタグであるheader
タグを使用します。
div
タグでもエラーになったり、デザインが崩れることはないのですが、検索エンジンのクロールを向上させるSEO対策とコードの可読性UPという保守性の観点からHTML5から追加されたタグは積極的に使用してください。
以降の記事でも積極的にHTML5から追加されたタグを使用します。
HTML5から追加されたタグにはどんなものがあるか知りたい方は、以下の記事をご参考にしてください。
v-app-barタグ追加
v-app-bar
タグを使用することでヘッダーのナビゲーションバーのスタイルを実現することができます。
以下に今回使用しているオプションをまとめました。
app | v-app-bar のオプション。高さをいい感じに自動調整してくれる。ヘッダーのナビゲーションバーを実現する際は、 v-app-bar タグと必ずセットで使用。 |
---|---|
dark | v-app-bar のオプション。v-app-bar ディレクティブに適用するデザインテーマの種類。darkテーマを設定すると、バーの背景色が黒色になり、文字の色は白に変わる。他にもlightやprimaryが指定可能。他にもどんなテーマがあるか気になる方は、こちら。 |
今回ご紹介したオプション以外に何があるか確認したい方は、以下の公式ドキュメントをご参照ください。
v-toolbar-titleタグ
ヘッダーに上記のサンプル画像のようなタイトルを表示したいときはv-toolbar-title
を使用します。
以下が今回のポイントとなります。
■ SEO対策と保守性向上のため、HTML5以降に追加されたタグを積極的に使用する。
■ ヘッダーのナビゲーションバーを実装するときは、v-app-bar
タグとapp
ディレクティブを使用する。
■ ヘッダーのナビゲーションバーのタイトルはv-toolbar-title
タグを使用する。
ヘッダーのハンバーガーメニュー作成方法
次にヘッダーに下図のようなハンバーガーメニューを表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<template> <v-app> <header> <v-app-bar app dark > <!-- ここから追加 --> <v-app-bar-nav-icon @click="drawer = true"></v-app-bar-nav-icon> <!-- ここまで追加 --> <v-toolbar-title>MyPortfolioSite</v-toolbar-title> </v-app-bar> </header> </v-app> </template> <script> // ここから追加 export default { data () { return { drawer: false } } } // ここまで追加 </script> <style></style> |
作業内容
① v-app-bar-nav-icon
タグを追加
② クリックイベントを追加
③ script
タグ内にデータ定義
v-app-bar-nav-icon
タグを使用することで、ハンバーガーメニューのアイコンを表示することができます。
クリックイベントを追加
@click
ディレクティブはVuejsのディレクティブです。
@click
ディレクティブを使用することでJavascriptの実行が可能になります。
また、@click
は省略記法なのですが、省略せずに書くとv-on:click
となります。
実務では省略記法で書くことが多いため、今回のサンプルでは省略記法で統一します。
1 2 |
@click="Javascriptの処理" v-on:click="Javascriptの処理" |
なお、click
部分はmouseover
など他のDOMイベントも使用可能です。
今回の@click="drawer = true"
部分を解説すると、v-app-bar-nav-icon
(ハンバーガーメニュー)がクリックされたら、drawer
という変数へtrue
という値を代入するという意味になります。
では、drawer
という変数はどこで定義するのかということについて、次に説明します。
データ定義
Vue.jsのコンポーネント内で変数を定義したいときは、script
タグ内に以下のようにコーディングします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<script> // ES5の書き方 export default { data: function () { return { 変数名: 値 } } } // ES6の書き方 export default { data () { return { 変数名: 値 } } } </script> |
このように変数を定義することでtemplate
タグ内から変数を呼び出すことができます。
なお、上記でES5とES6の書き方を両方紹介しましたが、今回のサンプルではES6の記法でコーディングします。
以下が今回のポイントとなります。
■ ハンバーガーメニューのアイコンを表示する際はv-app-bar-nav-icon
タグを使用する。
■ @click
ディレクティブを使用することでJavascriptの実行が可能。
■ データ定義する際は、data
プロパティを使用し、return
部分にオブジェクト形式でデータ定義する。
ヘッダーのサイドメニュー作成方法
次にヘッダーのハンバーガーメニューを押下すると、下図のように表示されるサイドメニューを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<header> <v-app-bar app dark > <v-app-bar-nav-icon @click="drawer = true"></v-app-bar-nav-icon> <v-toolbar-title>MyPortfolioSite</v-toolbar-title> </v-app-bar> <!-- ここから --> <v-navigation-drawer v-model="drawer" fixed temporary > <v-list nav dense > <v-list-item-group> <v-list-item> <v-list-item-title>HOME</v-list-item-title> </v-list-item> <v-list-item> <v-list-item-title>ABOUT</v-list-item-title> </v-list-item> <v-list-item> <v-list-item-title>WORK</v-list-item-title> </v-list-item> <v-list-item> <v-list-item-title>SERVICE</v-list-item-title> </v-list-item> <v-list-item> <v-list-item-title>BLOG</v-list-item-title> </v-list-item> <v-list-item> <v-list-item-title>ACCESS</v-list-item-title> </v-list-item> </v-list-item-group> </v-list> </v-navigation-drawer> <!-- ここまで --> </header> |
作業内容
① v-navigation-drawer
タグを追加
② v-list
タグを追加
こちらは画像のようなサイドメニューを表示するUIコンポーネントとなります。
以下に今回使用しているオプションをまとめました。
fixed | position:fixed のスタイルが効き、サイドメニューが画面左側いっぱいに表示することが可能。 |
---|---|
temporary | アプリケーションの一番上の層で表示させることが可能。サイドメニューの一部がヘッダーから隠れたりするのを防ぐ。 |
他にも右側にサイドメニューを表示するためのオプション等ありますので、カスタマイズしたい方は公式ドキュメントをご参照ください。
v-model:双方向データバインディング
v-model
は下図のように双方向にデータを同期する双方向データバインディングを行うことができます。
data
プロパティ側の変数で更新があったら、v-model
内で使用してる変数を更新し、v-model
内で使用してる変数で更新があったら、data
プロパティ側の変数を更新するというような同期処理が行われます。
v-model
の書き方は以下の通りです。
1 |
v-model="データ変数" |
今回の例でいうと、下図のような双方向データバインディングが行われています。
ただし、v-model
は通常input要素やtextarea要素、select要素などのフォームに使用され、今回のようなユースケースはレアです。
Vuetify特有の書き方なので、「v-navigation-drawer
を使用するときは、表示非表示の制御にはv-model
ディレクティブを指定するんだなー」ぐらいの理解でOKです。
v-listタグ
v-listタグ
は以下のような構成となっております。
コーディングする際は、以下のように書きましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<v-list> <v-list-item-group> <v-list-item> <v-list-item-title>アイテム1</v-list-item-title> </v-list-item> <v-list-item> <v-list-item-title>アイテム2</v-list-item-title> </v-list-item> <v-list-item> <v-list-item-title>アイテム3</v-list-item-title> </v-list-item> </v-list-item-group> </v-list> |
以下に今回使用しているv-list
のオプションをまとめました。
nav | リストの各アイテムの要素をいい感じに丸みをつけてmarginを設定してくれる。 |
---|---|
dense | リスト全体のフォントを小さくし、いい感じにmarginを設定してくれる。 |
カスタマイズしたい方はv-listの公式ドキュメントを参考に様々なオプションを試してみてください。
以下が今回のポイントとなります。
■ サイドメニューを作成する際は、v-navigation-drawer
タグを使用する。
■ v-model
ディレクティブを使用することでサイドメニューの表示・非表示の制御が可能。
■ v-list
タグを使用することでいい感じのリストスタイルになる。
v-forディレクティブでソースコードの簡略化
以下のサイドメニューのリストのアイテム(HOME等)ですが、PC時のヘッダーメニューでも同じものを使用するため、共通化しておきましょう。
また、v-forディレクティブを使用することでソースコードを簡略化できます。
それでは、実際にリファクタリングしていきます。
まず、simple-vue-website-sample/src
ディレクトリにcommon
ディレクトリを作成し、変数を管理するconstants.js
を新規作成します。
ちなみにconstantsは変数という意味です。
1 2 3 |
$ cd ~/simple-vue-website-sample/src $ mkdir common $ touch constants.js |
次に以下のようにname(メニューに表示する名前)とurl(遷移先)を定義します。
遷移先については、vue-routerを導入してから設定するため、一旦#
を仮で設定しておいてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
export default { menuItems: [ { name: 'HOME', url: '#' }, { name: 'ABOUT', url: '#' }, { name: 'WORK', url: '#' }, { name: 'SERVICE', url: '#' }, { name: 'BLOG', url: '#' }, { name: 'ACCESS', url: '#' } ] } |
次に、App.vueのscript
タグに以下のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 |
<script> import constants from './common/constants' // 今回追加 export default { data () { return { drawer: false, menuItems: constants.menuItems // 今回追加 } } } </script> |
import文で先程作成したconstants.js
を読み込み、menuItems
という変数にリストを格納しております。
constants.menuItems
と指定することで先ほどconstants.js
で定義したオブジェクトのvalueが取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
[ { name: 'HOME', url: '#' }, { name: 'ABOUT', url: '#' }, { name: 'WORK', url: '#' }, { name: 'SERVICE', url: '#' }, { name: 'BLOG', url: '#' }, { name: 'ACCESS', url: '#' } ] |
次にtemplate
タグのv-list-item
要素をv-for
ディレクティブを使用して、以下のように修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<v-list nav dense > <v-list-item-group> <!-- ここから追加 --> <v-list-item v-for="(menuItem, index) in menuItems" :key="index" > <v-list-item-title>{{ menuItem.name }}</v-list-item-title> </v-list-item> <!-- ここまで追加 --> </v-list-item-group> </v-list> |
v-forディレクティブの使い方
v-for
ディレクティブを下記のように使用することで、ビルドする際に指定したリストの中身をひとつずつ取り出し、要素を作成してくれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// 変数 items=["アイテムA", "アイテムB", "アイテムC"] // ビルド前 <li v-for="(item, index) in items" :key="index"> <p>{{ item }}</p> </li> // ビルド後 <li> <p>アイテムA</p> <p>アイテムB</p> <p>アイテムC</p> </li> |
item | 繰り返し処理で一時的にデータを格納するために使用。変数名は何でもOK。また、変数を要素内で使用するには二重カギカッコ{} で囲む必要がある(※)。 |
---|---|
items | data プロパティで定義した変数を指定する必要がある。 |
index | 第2引数に指定することで、for文で読み込まれた順番(配列の順番)を取得できる。使用しない場合は省略可能。 |
:key | 一意となる値をセット。 |
(※) v-for構文内の変数に限らず、data
プロパティ内で定義した変数を要素内で使用する場合にも二重カギカッコ{}
で囲む必要があります。
補足:keyに指定すべき値
今回のサンプルプログラムでは、:key
にindex
を指定しましたが、リストに対し、追加削除したりする場合は、以下のようにデータに一意の値を指定することをおすすめします。
1 2 3 |
<li v-for="item in items" :key="item"> <p>{{ item }}</p> </li> |
今回のサンプルでは問題ないのですが、リストに対し、追加・削除する場合は、indexが変わってしまうため、予期しない挙動となってしまう可能性があります。
詳しい理由が知りたい方は以下のQiitaの記事をご参照ください。
さいごに、動作確認して、リファクタリング前と同じ結果になれば、リファクタリング完了です。
以下が今回のポイントとなります。
■ 変数は保守性を考えて外部ファイルで一元化する。
■ 繰り返し処理はv-for
ディレクティブを使用してソースコード簡略化
さいごに
ここまででスマホのヘッダーのコーディングは完了です!
お疲れ様でした!
少し休憩して、次回はPCのヘッダーを実装していきましょう!
ES6について基礎から学習したい方は、以下の記事で紹介している教材がおすすめです。
VueJsの基礎知識についてより詳しく網羅的に学習したい方は、以下の記事で紹介している教材がおすすめです。
JavaScriptの基礎からVueJsが学べるスクールは以下の記事で紹介しております。
さいごまで読んでいただき、ありがとうございました。
知り合いから
「フリーランスエンジニアになれば、年収800万円以上の高報酬でかつ、自由な働き方をチョイスできる」
というのを聞いて、フリーランスエンジニアに興味を持ったのですが、
当時SIer企業でエンジニアをやっていたボクはなかなか一歩踏みだせませんでした。
というもの以下のような不安があったからです。
■フリーランスエンジニアってかなりの技術力がないとなれないのではないのか?
■フリーランスエンジニアって不安定なのではないのか?
■フリーランスエンジニアって人脈やコネ、営業力が必要なのではないのか?
しかし、実際にフリーランスエンジニアになってみて気づきました。
これらはすべて間違いです。
過去のボクのようにフリーランスエンジニアに興味あるけど一歩踏み出せないという方向けに
『フリーランスエンジニア転職完全ロードマップ』
という記事を書きました。
この記事読めば、どうすればフリーランスになれるのかが分かりますので、ぜひ一読ください。