2019.10.9
Vueでカクテルデータベースをリファインする話#10【UIフレームワーク#2】
前回、導入が終わったので、実装のほうに入ります。
とはいえ、現段階でやりたいのは親フレーム部分とポップアップ部分ぐらいなので、そのへんをうまくできればとりあえずVuetifyに関してはいいかなって感じです。
ってなわけで、デフォルトで用意されているUIをサクっと導入してしまいましょう・・・・・・と思ったんですが、サイドバーなど必要のない機能が入ってたので、ここの導入は見送ります(笑)
bootstrapのように、必要なところだけを組み込む感じでも別にいいかな・・・・・・という気がしてきたので今回はそんな感じに実装していきます。
じゃあbootstrapでいいじゃん
このサイトが割とわかりやすかったので、そちらを参考にすすめていきましょう。
<v-app>
<v-content>
<v-container>
<v-layout wrap>
<v-flex xs12 sm6 md4 text-center my-5><v-btn>押して</v-btn></v-flex>
<v-flex xs12 sm6 md4 text-center my-5><v-btn >押して</v-btn></v-flex>
<v-flex xs12 sm6 md4 text-center my-5><v-btn>押して</v-btn></v-flex>
</v-layout>
</v-container>
</v-content>
</v-app>
これで基本的なタグの構成がわかりますね。
v-appはすべてのタグの親になるべき存在なので、ルートコンポーネントにこれを含ませればすべて解決です。
v-containerに関しては、サイドメニューと連動させるために必要なタグ、とのことですね。今回の場合は正直不要ではある感するのですが怖いので削除しないのでそのまま使用します(笑)
v-layoutは、bootstrapのグリッドシステムみたいなもんですね。この子に
v-flexを適用することでいい感じに配置してくれるみたい。
ちなみに
wrapというオプションをつけないと改行してくれないらしい。
どういう仕様それ???
これに、ヘッダーとフッターをつけたい、って感じですね。つけましょう。
個人的な要望としては
ヘッダーはスクロール追随、フッターはページ最下部固定って感じにしたいですね。現行デザインだとフッターはないと思うんですけど、この際つけちゃいましょ。
<template>
<v-app>
<div>
<v-app-bar>
<!--ヘッダー内容-->
</v-app-bar>
</div>
<v-content>
<v-container>
(中略)
</v-container>
</v-content>
<v-footer>
<!--フッター内容-->
</v-footer>
</v-app>
</template>
まぁそのまんまですね。注意すべきことは、v-app-barの親のdivですね。これがないとうまく動かないらしい。
意味わかんねえ・・・・・・
公式ドキュメントのAPI説明を見ます。オプションで色々指定するといいみたい。このへんの書き方は初心者向けでは全く無いですね。プログラミング経験者向けですね。
まぁVue自体node.jsを必要とするぐらいですしね・・・・・・とりあえず今回使ってるのはv-app-barなので、App barsの項目を参照。fixedが使えそう。設定してみます。
<div>
<v-app-bar fixed>
<!--ヘッダー内容-->
</v-app-bar>
</div>
これでいけます。簡単っすね。
あと気になるのはモーダルですね。これはVuetifyではダイアログを使って実装するみたいですね。
公式ドキュメントを見て使えそうなサンプルを探します。この場合
オーバーフローが使えそうですね。
できましたあ♥
<v-dialog v-model="dialog" width="600px">
<template v-slot:activator="{ on }">
<v-btn color="primary" dark v-on="on">Open Dialog</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">Use Google's location service?</span>
</v-card-title>
<v-card-text>
aaaaa
</v-card-text>
<v-card-actions>
<div class="flex-grow-1"></div>
<v-btn color="green darken-1" text @click="dialog = false">Disagree</v-btn>
<v-btn color="green darken-1" text @click="dialog = false">Agree</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
v-slot:activatorにonイベントを渡すと、対応したもののイベントが発火する仕組みらしい。clickじゃないのか・・・・・・?
その下のボタンにv-on="on"があるんですけど、もしかしてこっちが対応してんの・・・・・・?って思ったんですが、やはり名前はonのままじゃないとダメみたい。やはりこのonはイベントハンドラのonらしい。じゃあなんでv-on="on"だなんて回りくどい書き方してんだろ・・・・・・。
さて、このままだと明らかにコードとして長いので、ダイアログ部分を切り出します。どういう切り出し方がいいかな・・・・・・。
現行のデザインだと、トップページ下部にあるフォームと共通化するので、少なくともそこで分けることになりそうですね。
モーダルの場合、そのラッパーも要ると思うので、最終的にはそんな感じの構造になりそうです。
もうちょっと踏み込んで考えましょうか。具体的にこのコンポーネントの記述はSQLの結果に依存して描写されます。どんなリキュールがカテゴリとしてあるのかはサーバー側にデータがあるので、そこから取ってくる形になります。
これ、コンポーネントが完全に独立してると、2回アクセスして取ってくることになっちゃうと思うんですよね。なので、このへんのカラムの状態とかはVuexにデータを持たせます。
アクセスされたとき、データがなかったらサーバーにデータを取りに行く、みたいな形で良さそうですね。
というのを将来的にやるって踏まえた上でコンポーネントを切り出しましょう。
v-cardの内部にコンポーネントを挟み込めばいけそうな感じはしますね。
さて、切り出し方ですね。普通にやってもいいんですが、将来性とか考えて
こういう実装にしようかなと。
そもそも、単純にコンポーネントだけを切り出すとこんな警告が出てくるので・・・・・・。
dialogっていうプロパティ?が切り離されちゃうのが原因だと思われます。これの真偽で状態を管理してるっぽい・・・・・・?
ちなみに、上記リンクの手法を雑に試してみたところやはり動きませんでした(笑)
原因はこれでしょうか・・・・・・?vueのバージョンがわからないんですが(笑)、基本的にはactivatorを使ったほうがいいらしい・・・・・・。
なるべく本番の環境に合わせてコードを書かないといけないのですが、コンポーネントを多重で定義しようと思うと、このdialogという変数にアクセスするためにいろいろ引きずり回すことになりそうな予感がします。いわゆるバケツリレーですね。
その実装は明らかにマズい。
なので、対応策を考えます。
まず、どこでコンポーネントを切り分けるか、ですね。これはいろいろ考えられるのですが、一番手っ取り早そうなところとして、v-card部分を外に抜き出してしまうことにします。まずはね。
で、こうなると先程申し上げた通り、dialogの状態に関して、親から子にアクセスできなくなる、っていうのが問題になるみたいです。
こういうサンプルプログラムもありますね。
これを見るに、コンポーネントはカード部分で切り離すより、ボタン部分からごっそり行っちゃった方がいい気がしてきましたね。フォーム部分だけ別コンポーネントにすればいいわけですし・・・・・・そうしよっかな。
まぁそうなるとdialogの分離自体起こらなくなって練習にはなんなくなりますけどね(笑)
これに関しては普通に切り抜くだけで動作するので良しとしましょう。
相変わらずダイアログの警告が出てるんですがこれに関しては原因がわからなくなっちゃったので放置でいいでしょ・・・・・・()
んじゃ次回はいよいよ、カクテル検索の方に入りましょうかね。これができればほぼ半分はリファイン完了といって差し支えありません。