- 投稿日:2021-01-25T20:07:19+09:00
[Laravel7.x]ドキュメントを読みながらVuetifyを導入する
今回の題
VuetifyをLaravelに導入する手順を書き残します。
ドキュメントを読みながら出来るだけ忠実に導入していきます。環境
- Laravel 7.
- Vue.js 2.5.17
- Vuetify 2.4.3
手順
1 Laravelのインストール
readouble - Laravel 7.x インストールの通りにインストールします。
- インストーラを使うのであれば
$ composer global require laravel/installer $ laravel new プロジェクト名
- Composerのcreate-projectコマンドを使うなら、
$ composer create-project --prefer-dist laravel/laravel プロジェクト名その後、プロジェクトに移動して以下を実行。
$ php artisan servehttp://localhost:8000にアクセスしてLaravelの初期画面が確認できればOK。
2 Vue.jsのインストール
readouble - Laravel 7.x JavaScriptとCSSスカフォールド
を読みながらインストールします。まずは、laravel/uiのインストール。
$ composer require laravel/ui
laravel/ui
はLaravel6から用いられる、Bootstrap、React、Vueなどのフロントエンドパッケージをインストールする為のライブラリ。laravel/uiのインストールを終えたら、以下でVue.jsのスカフォールドを作成。
$ php artisan ui vuepackage.jsonはこんな感じ。Vue.jsの項目もちゃんとできてます。
package.json"devDependencies": { "axios": "^0.19", "cross-env": "^7.0", "laravel-mix": "^5.0.1", "lodash": "^4.17.19", "resolve-url-loader": "^2.3.1", "sass": "^1.20.1", "sass-loader": "^8.0.0", "vue": "^2.5.17", "vue-template-compiler": "^2.6.10" }bootstrapは使用しないので消し、依存関係にあるjquery、poper.jsも消しました。
npm installを実行。
$ npm installapp.jsを編集。
bootstrapを読み込んでいる以下の箇所を消します。resource/js/app.js- require('./bootstrap');Vue.jsはこれでOK。
試しにLaravelが用意してくれているコンポーネントを読み込んでみます。
resources/views/welcome.blade.php
を以下のように変更します。resources/views/welcome.blade.php<!DOCTYPE html> <html lang="{{ app()->getLocale() }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <link rel="stylesheet" href="{{ mix('css/app.css') }}"> <title>{{ config('app.name', 'Laravel') }}</title> </head> <body> <div id="app"> <v-app> <example-component></example-component> </v-app> </div> <!-- js読み込み --> <script src="{{ mix('js/app.js') }}"></script> </body> </html>以下でコンパイルを行い、
$ npm run hothttp://localhost:8000にアクセスして確認。
bootstrapを消したのでスタイルが当てられていないと思いますが、後にVuetifyを導入してスタイルを当てるので問題ありません。3 Vuetifyのインストール
Vuetifyの公式ドキュメントを読みながらインストールします。
vuetifyjs - WebpackでのインストールVuetifyのインストール。
$ npm install vuetify --save-devVuetifyのドキュメントではsassとsass-loaderもインストールしていますが、Laravelにはデフォルトでpackage.jsonにそれらの記述があります。
なので、Vue.jsをインストールした時のnpm install
で既にインストールされていますのでここで行う必要はありません。ドキュメント通り、pluginsディレクトリを作成し、そこに
vuetify.js
を作成します。$ mkdir resources/js/plugins $ cd resources/js/plugins $ touch vuetify.jsvuetify.jsを以下のように編集。
resources/js/plugins/vuetify.jsimport Vue from 'vue' import Vuetify from 'vuetify' import 'vuetify/dist/vuetify.min.css' Vue.use(Vuetify) const opts = {} export default new Vuetify(opts)app.jsで読み込みます。
resource/js/app.jsimport Vue from 'vue'; import Vuetify from './plugins/vuetify' // vuetify.jsを読み込み import ExampleComponent from './components/ExampleComponent.vue' const app = new Vue({ el: '#app', vuetify: Vuetify, components: { ExampleComponent, } });これでVuetifyの導入は完了です。
4 マテリアルデザインのインストールとフォントの適応
一度ここまでの設定で、ドキュメントに掲載されているCardsの例を表示してみます。
↓こういうの。
では、
components/ExampleComponent.vue
を以下のように編集(コピペ)。resource/js/components/ExampleComponent.vue<template> <v-card :loading="loading" class="mx-auto my-12" max-width="374" > <template slot="progress"> <v-progress-linear color="deep-purple" height="10" indeterminate ></v-progress-linear> </template> <v-img height="250" src="https://cdn.vuetifyjs.com/images/cards/cooking.png" ></v-img> <v-card-title>Cafe Badilico</v-card-title> <v-card-text> <v-row align="center" class="mx-0" > <v-rating :value="4.5" color="amber" dense half-increments readonly size="14" ></v-rating> <div class="grey--text ml-4"> 4.5 (413) </div> </v-row> <div class="my-4 subtitle-1"> $ • Italian, Cafe </div> <div>Small plates, salads & sandwiches - an intimate setting with 12 indoor seats plus patio seating.</div> </v-card-text> <v-divider class="mx-4"></v-divider> <v-card-title>Tonight's availability</v-card-title> <v-card-text> <v-chip-group v-model="selection" active-class="deep-purple accent-4 white--text" column > <v-chip>5:30PM</v-chip> <v-chip>7:30PM</v-chip> <v-chip>8:00PM</v-chip> <v-chip>9:00PM</v-chip> </v-chip-group> </v-card-text> <v-card-actions> <v-btn color="deep-purple lighten-2" text @click="reserve" > Reserve </v-btn> </v-card-actions> </v-card> </template> <script> export default { data: () => ({ loading: false, selection: 1, }), methods: { reserve () { this.loading = true setTimeout(() => (this.loading = false), 2000) }, }, } </script>赤枠で囲んだ部分に表示されるはずの星マーク(v-rating)が表示されていません。
理由はマテリアルデザインアイコンをインストールしていないから。
ドキュメントによると、Vuetify uses Google’s Roboto font and Material Design Icons.
だそうなので、マテリアルデザインアイコンのインストールとグーグルフォントの適応を行います。
方法は二つ。
方法その1 - CDNを使う
最もシンプルな方法としてドキュメントで紹介されている方法です。
以下の2つをhead内に付け足すだけ。<!-- グーグルフォント --> <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"> <!-- マテリアルデザインアイコン --> <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">方法その2 - インストールする
まずはマテリアルデザインアイコンのインストール。
npm install --save @mdi/font
plugins/vuetify.js
の編集。resources/js/plugins/vuetify.jsimport Vue from 'vue' import Vuetify from 'vuetify' import 'vuetify/dist/vuetify.min.css' import '@mdi/font/css/materialdesignicons.css' // 追記 Vue.use(Vuetify) // opt内にiconfontを追記して適応させる const opts = { icons: { iconfont: 'mdi', }, } export default new Vuetify(opts)続いて、グーグルフォントを適応させる。
resources/sass/app.scss// Fonts // @import url('https://fonts.googleapis.com/css?family=Nunito'); // ↓ 以下に変更 @import url('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900'); // Variables @import 'variables';これでOK。
コンパイルして再度ブラウザで確認してみると……。完璧?
わかりづらいですがフォントもしっかりと適応されています。以上!!!
参考
- 投稿日:2021-01-25T17:43:23+09:00
v-slotの値で変数を使って動的に扱う方法
v-slotとは
やりたいこと
v-slot
の値を動的に扱いたい。例えばVuetifyのDataTableで
v-slot
を使うサンプルで、Data table component — Vuetify
<template v-slot:item.calories="{ item }"> <v-chip :color="getColor(item.calories)" dark > {{ item.calories }} </v-chip> </template>
item.calories
を動的にしたい場合です。やり方
vueの2.6.0から対応されていて、
[]
で値を囲めば良いです。先の例だと、
<template v-slot:[`item.${someVar}`]="{ item }"> <v-chip :color="getColor(item.calories)" dark > {{ item.calories }} </v-chip> </template>という事です。
他にも
v-for
と組み合わせて<template v-for="one in array" v-slot:[`item.${one}`]="{ value }"> {{ value.hoge }} </template>というのもできます。tableの列が増減するようなパターンで使えます。
- 投稿日:2021-01-25T17:32:01+09:00
Vue.js でダブルクオーテーションマークの中で computed や data プロパティの値を使う
初投稿且つ初学者なので、至らない点も多々あると思いますがご容赦ください?♂️
前置きが長くなってしまったのでお急ぎの方は目次から解決策をご覧ください。computed や data プロパティの値を使う際に、HTML側では二重括弧を用いたり、JS側では thisのスコープを用いたりすると思いますが、URL内のダブルクオーテーションマーク内で使う際に詰まってしまいました。
経緯
署名付きURLの発行をしてS3にファイルを保存した
AWS S3と Laravel、Vue.jsを用いてポートフォリオを作成しているのですが、S3にファイルを投稿詳細別に保存していました。署名付きURLは発行して保存すべく、以下のような感じにしていました。署名付きURLの発行方法はこちらを参照にしました。
参考: https://qiita.com/tatsuroooK/items/48e3475625105ace3d6c
async getPresignedUrl() { let filename = this.username + '/' + this.$route.params['id']; let filetype = 'audio/*'; let fileext = 'mp3'; try { const url = '/api/get-presigned-url?filename=' + filename + '&filetype=' + filetype + '&fileext=' + fileext; let response = await axios.get(url); console.log('S3署名付きURL取得 成功'); console.log(response); return response; } catch (error) { console.log('S3 署名付きURL取得 失敗'); } },let filename = this.username + '/' + this.$route.params['id'];こちらをみていただければ分かりますが、ユーザー名と投稿の主キーのidを用いてユーザーの投稿ごとにURLを発行しています。this.username でユーザーネームを呼び出せるように computed 内で記述、this.$route.params['id'] で投稿のidを取得できるようにしてます。
参考
https://www.hypertextcandy.com/vue-laravel-tutorial-authentication-part-4/
https://qiita.com/tseno/items/4b299464c4fc5605e515ユーザーが閲覧できるようにしたかった
さて、これで無事S3にアップできるようになりました。
保存したファイルにはこんな感じのURLでアクセスできるのでユーザーが閲覧できるように記述します。音声ファイルなのでaudioタグを用います。"https://バケット名.s3-ap-northeast-1.amazonaws.com/フォルダ名/ユーザー名/投稿のid.mp3"
<audio controls :src="https://バケット名.s3-ap-northeast-1.amazonaws.com/フォルダ名/{{username}}/{{ this.$route.params['id'] }}.mp3" />ダブルクオーテーションマークの中では二重括弧でプロパティを呼び出せないことに気づく
プロパティを呼び出す時は二重括弧を用いますが、 src はダブルクオーテーションマークで括らないといけないので使うことができません。
そこでテンプレートリテラルやシングルクオーテーションマークで色々試してみましたがうまくいかず。もはや何通り試したのか覚えてない。
解決策
手順① 呼び出したい値をdataプロパティに移動させる
先ほどまでusernameはcomputedプロパティから呼び出していましたが、dataプロパティに移動させます。
data() { return { //一部省略 username: this.$store.getters['auth/username'] }; },dataプロパティの値はComputedプロパティで呼び出せます。
手順② ComputedプロパティにURLを宣言
dataプロパティの値はcomputedプロパティで呼び出せるが、その逆はできませんでした。(やり方があるのかもしれませんが、、) 二重括弧とかテンプレートリテラルを使う必要はありませんが、+ をつけないと読み込んでくれません。
vue.jscomputed: { //一部省略 url() { return "https://dictationmanager.s3-ap-northeast-1.amazonaws.com/ファイル名/"+this.username+"/"+this.$route.params['id']+".mp3"; } },投稿詳細のidを表す this.$route.params['id'] は特に変更しなくてもそのまま呼び出せます。どういう理屈なのかは分かりませんが。
手順③ タグ内で呼び出す
<audio controls :src="url" />参考 : https://yoshiyukieng.com/vuejs-vbind-img-src/
結論
dataプロパティ、computedプロパティを併用してダブルクオーテーションマーク内でプロパティを呼び出すことに成功しました。「絶対にこんな周りくどいやり方しなくてもいけるやろ、、」と薄々思っていましたが、自力でこのやり方を発見できたことに意味があるということにします。data とか computed とか vue でよく使われるオプション?もまだまだ理解できてないところがあるので、勉強してきます。
PS もっといい方法をご存知の方いらっしゃれば教えていただけると幸いです?♂️
- 投稿日:2021-01-25T17:13:17+09:00
vueで親コンポーネントと子コンポーネントのクリックイベントを切り分ける
子コンポーネント全体にクリックイベントがあり、親コンポーネントにもクリックイベントがある場合、親コンポーネントをクリックした際に子コンポーネントのクリックイベントも発火してしまう(はず)
例えば親コンポーネントでこういった処理をしたい場合
<v-row> <v-col @click="parentEvent()"> //親コンポーネントでクリックイベントを上書きしたい <ProjectListView></ProjectListView> //このコンポーネント自体にもクリックイベントがある </v-col> </v-row>親コンポーネントの子コンポーネントを使う囲みタグのイベント修飾子にcaptureを設定し、子コンポーネントにはstopを設定する
<v-row> <v-col @click.capture="parentEvent()"> <ProjectListView @click.stop="" ></ProjectListView> </v-col> </v-row>captureでルートからイベントを追って、子コンポーネントではstopでイベントを止める
正直よくわかってません、もっといいやり方あったら教えてください
- 投稿日:2021-01-25T15:56:43+09:00
【Vuetify】v-data-table のレスポンシブデザインがデプロイ後に崩れる
環境
Vue.js 2.6.12
Vuetify 2.3.21事象
開発中のアプリケーションの一部にVuetifyのexpanded付きv-data-tableを利用しています。expandedの配列の中にs3にアップロードした画像URLが含まれています。まずデバッグツールでテスト操作を行い問題ないことを確認後にデプロイ、スマホ端末で実際にサイトにアクセスし確認してみるとレスポンシブデザインが崩れるという問題が発生していました。
Qiitaやstackoverflowなど色々当たっても同様の報告が見当たらなかったので、ご参考まで私自身の回避策を共有させていただきます。具体的には下の動作を見ていただいた方が早いかと思います。(横方向へのスライド操作は想定していません)
(説明)
スマートフォンではユーザー毎の投稿を下方向にスライドして見ることが出来、かつ「^」の展開ボタンをクリックすると投稿に紐づくさらに詳細なグラフやコメントが確認できるようになります。
本来は下方向にしかスライドできないはずなのに、1:展開ボタンをクリックして投稿の詳細を展開 2:展開ボタンをさらにクリックして展開された行を閉じると、何故か次の投稿が横方向に並んでしまいます。原因がハッキリしておらず推測ですが、expandedに画像データを含めると発生してしまうため、展開されるexpandedの情報の中に画像データが最初にURLとしてレンダリングされる事と関係しているのかと考えています。回避策
モバイル端末での閲覧時には展開ボタンをクリック時に強制的に再レンダリングを行うように変更する強制的にtableタグのwidthを固定させる事で解決しました。(styleでのwidth指定やvue.jsのwatchを使ったwidth操作は色々試しましたがうまくい機能しませんでした・・・)
ポイントは
1. mixinによるwindow.addEventListener
を使ったisMobile
props(boolean型)による閲覧端末がモバイル端末か否かの判定
2.v-data-table
タグ内の:key
propsの設定ですisMobileの判定
私は以下のmixinを
app.vue
にimportをして常にisMobile
の情報を取得するようにしました。mixinexport default { data: () => ({ isMobile: false, }), beforeDestroy () { if (typeof window === 'undefined') return window.removeEventListener('resize', this.onResize, { passive: true }) }, mounted () { this.onResize() window.addEventListener('resize', this.onResize, { passive: true }) }, created () { }, methods: { onResize () { this.isMobile = window.innerWidth < 450 }, }, }v-data-tableのprops
ここの
:key
にisMobile
がtrueの時のみexpanded.length
がバインドされ、変更時にv-data-table
が再レンダリングされます。expanded.length
は現在展開している行数となるので、つまり、展開ボタン『^』をクリックするたびに再レンダリングされtable
タグのwidth
が強制的に固定されます。<v-data-table <!-- 省略 --> :single-expand="singleExpand" :expanded.sync="expanded" show-expand <!-- ポイント --> :key="isMobile ? expanded.length : ''" calculate-widths widths="100%" >
- 投稿日:2021-01-25T10:37:46+09:00
amplify-authenticator のサインアップを無効化する方法メモ
はじめに
ユーザーの登録は管理者側で行いたいので、amplify-authenticator(@aws-amplify/ui-vue) のサインアップリンクを無効化しようとしてハマったのでメモを残す。
isSignUpDisplayed: false
を食わせれば良いという記事はたくさんあるが、
肝心の食わせ方がまちまちでなかなか適用することができなかった。結論
<template> <amplify-authenticator> <amplify-sign-in slot="sign-in" hide-sign-up="true"></amplify-sign-in> <amplify-sign-out></amplify-sign-out> </amplify-authenticator> </template>
amplify-sign-in
にslot="sign-in" hide-sign-up="true"
を渡すことで無効化できた。参考リンク