- 投稿日:2021-01-18T23:25:41+09:00
【Nuxt.js】v-data-tableにリンクを埋め込む
v-data-table内ではNuxt-linkがうまく機能しなくて困っていましたが、
v-btnに「:to=」でリンクを仕込めました。
アイコン型のリンクする場合、v-btnの中にv-iconを組み込む。<v-data-table :headers="headers" :items="指定したいテーブル" item-key="id" > <template v-slot:[`item.actions`]="{ item }"> <v-btn icon :to="'/任意のリンク' + item.id" nuxt > <v-icon dark> mdi-pencil </v-icon> </v-btn> </template> </v-data-table>◆header部
headers() { return [ ※他の項目は省略しています { text: '操作', value: 'actions', sortable:false, } ]}◆バージョン情報
"nuxt": "^2.0.0"
"vue": "^2.6.12"
"@nuxtjs/vuetify": "^1.11.2"
- 投稿日:2021-01-18T21:40:48+09:00
【Vue.js】基礎知識
はじめに
現在、エンジニア転職活動中です。本日から、Vue.jsの学習を始めましたので、アウトプットとして記述していきます。
なぜVue.js?
なぜ、Vue.jsの学習を始めたのかを記載します。
・転職活動用に作成しているポートフォリオが、HTML,CSSとBootstrapの多用により、サイトに動きがないため。
・GoogleTrendsにて比較を見た結果、Vue.jsの比率が高く、今後入社した際にも、Vue.jsを採用されているまたは今後採用する予定の企業も多いと感じたため(https://trends.google.com/trends/explore?date=today%205-y&q=vue.js,react.js,angular.js)
・これまでRuby,Ruby on Railsの学習に注力しており、フロントエンドの知識があまりなかったため以上の理由により、Vue.jsの学習を初めていきたいと思いました。
導入方法
Vue.jsの導入はダウンロードまたはCDNを利用する方法がありました。
今回はCDNを利用してVue.jsを読み込むことで、利用していきます。index.html<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>基本機能
テキストのバインディング
index.html<div id="app"> <p>{{ message }}</p> </div>practice.jsvar app = new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } })繰り返し
index.html<div id="app"> <ul> <li v-for="item in list">{{ item }}</li> </ul> </div>practice.jsvar app = new Vue({ el: '#app', data: { list: ['野球', 'サッカー', 'バスケットボール'] } })イベント発火
index.html<div id="app"> <button v-on:click="handleClick">Click</button> </div>practice.jsvar app = new Vue({ el: '#app', methods: { handleClick: function(event) { alert(event.target) } } })フォーム入力の同期化
index.html<div id="app"> <p>{{ message }}</p> <input v-model="message"> </div>practice.jsvar app = new Vue({ el: '#app', data: { message: '' } })条件分岐
index.html<div id="app"> <p v-if="show">Hello Vue.js!</p> </div>practice.jsvar app = new Vue({ el: '#app', data: { show: true } })トランジションとアニメーション
index.html<div id="app"> <button v-on:click="show=!show">切り替え</button> <transition> <p v-if="show">Hello Vue.js!</p> </transition> </div>practice.jsvar app = new Vue({ el: '#app', data: { show: true } })practice.css.v-enter-active, .v-leave-active { transition: opacity 1s; } .v-enter, .v-leave-to { opacity: 0; }おわりに
本日学んだ基本知識です。明日以降構成の内容などアウトプットしていきたいと思います。
- 投稿日:2021-01-18T20:47:54+09:00
Laravel6 + Vue.js + Laravel SanctumのSPA認証でのアクセス制限の簡単な実装。
自分用なのでざっくりと。
時間がある時にもっと詳しい記事を書きたい。例えばdashboardページへ未認証ユーザーがアクセスしようとするとログインページへリダイレクトさせたい場合。
routes/api.phpRoute::middleware('auth:sanctum')->get('/authenticated', function () { return 'authenticated'; });resources/js/app.jsimport VueRouter from 'vue-router'; import DashBoard from "./components/DashBoard"; import LoginComponent from "./components/LoginComponent"; //〜略〜 const router = new VueRouter({ mode: 'history', routes: [ { path: '/login', name: 'login', component: LoginComponent, }, { path: '/dashboard', name: 'dashboard', component: DashBoard, beforeEnter: (to, from, next) => { axios.get('/api/authenticated') .then((res) => { if (res.data == 'authenticated') { next(); } }).catch(() => { next({ name: 'login' }); }); }, }, ] }); //〜略〜このようにすれば良い。
おまけ
最初は、
routes/api.phpRoute::middleware('auth:sanctum')->get('/authenticated', function () { return true; });resources/js/app.jsimport VueRouter from 'vue-router'; import DashBoard from "./components/DashBoard"; import LoginComponent from "./components/LoginComponent"; //〜略〜 const router = new VueRouter({ mode: 'history', routes: [ { path: '/login', name: 'login', component: LoginComponent, }, { path: '/dashboard', name: 'dashboard', component: DashBoard, beforeEnter: (to, from, next) => { axios.get('/api/authenticated') .then(() => { next(); }).catch(() => { next({ name: 'login' }); }); }, }, ] }); //〜略〜ってやってみて、実際にログインしてdashboardページにアクセスしようとしたら、
The Response content must be a string or object implementing __toString(), \"boolean\" given.っていう「booleanじゃだめよ!」っていうエラーが出てうまくいかなかったんだよねえ。。
でもとある外国人のYouTube動画ではこのやり方でうまくいってたんだよねえ。。
どうしてなんだろう。
まだまだ勉強不足みたいです。。
- 投稿日:2021-01-18T11:38:30+09:00
Viteとは何なのか
はじめに
ちょっと前に話題になっていた
Vite
について、どのようなものなのか調べつつまとめてみました。どのようなものなのか
従来のビルドツール(Vue CLI等)に比べて、高速で動作するビルドツールのようです。
公式サイトは下記。
https://vitejs.dev/
Vue.js
を開発されたEvan You氏が開発されました。
リポジトリは下記。(2021/01/18段階ではv2.0.0-beta.30
)
https://github.com/vitejs/vite
Vue.js
の他、React
Preact
のビルドもサポートしているようです。
- 開発時はバンドルが不要なので、開発サーバーの起動が早い。
- HMR(Hot Module Replacement)(画面の再描画なしに変更を適用してくれる機能)が、修正分のみを適応するため、
モジュールの総数に関係なくかなり高速。
といった利点があるようです。
この辺りは下記ドキュメントにより詳細に書いてあります。
https://vitejs.dev/guide/features.html導入はどのように行うのか
下記に手順があるので、そちらで行うことができそうです。
https://vitejs.dev/guide/まず、下記コマンドを実行します。
yarn create @vitejs/app
- (ここではプロジェクト名に
vite-project
を指定しています。)% yarn create @vitejs/app yarn create v1.22.4 [1/4] ? Resolving packages... [2/4] ? Fetching packages... [3/4] ? Linking dependencies... [4/4] ? Building fresh packages... success Installed "@vitejs/create-app@1.2.0" with binaries: - create-app - cva ✔ Project name: · vite-project Scaffolding project in /Users/hogehoge/workspace/vite/vite-project... ✔ Select a template: · vue-ts Done. Now run: cd vite-project npm install (or `yarn`) npm run dev (or `yarn dev`) ✨ Done in 66.19s.手順に沿って、下記を順に行なっていきます。
cd vite-project npm install (or `yarn`) npm run dev (or `yarn dev`)
- モジュールのインストール
% yarn yarn install v1.22.4 warning package.json: No license field info No lockfile found. warning vite-project@0.0.0: No license field [1/4] ? Resolving packages... warning vite > fsevents@2.1.3: "Please update to latest v2.3 or v2.2" warning vite > rollup > fsevents@2.1.3: "Please update to latest v2.3 or v2.2" [2/4] ? Fetching packages... [3/4] ? Linking dependencies... [4/4] ? Building fresh packages... success Saved lockfile. ✨ Done in 18.80s.
- サーバーの立ち上げ
% yarn dev Vite dev server running at: > Local: http://localhost:3000/ > Network: http://XX.XXX.XXX.XX:3000/ > Network: http://XX.XXX.XXX.XX:3000/ ready in 1319ms.毎度お馴染みの
http://localhost:3000/
にアクセスすると、下記が表示されます。
その他情報
Typescript
のサポートも行っているようですが、型チェックは行ってくれないようです。- 内部のトランスパイルには、 esbuild を使用しているそう。
この辺りの情報も公式に載っているので、ご興味のある方は是非。
https://vitejs.dev/guide/features.html#npm-dependency-resolving終わりに
チュートリアルで行ったようなプロジェクトでは、モジュール数も少ないため速度的にはわかりませんでしたが、
実プロジェクトで用いた時にどのような速度が出るかが気になるところです。
開発環境のサーバー起動、ビルド時間で悩みを抱えている方には、有益なツールなのではないでしょうか。
開発されているのがEvan You氏とのことで、今後の発展が楽しみなツールです。参考にした情報
- 投稿日:2021-01-18T08:49:47+09:00
困っている方必見!ページトップからある要素までの高さの取得方法
cssにてpositionを使っているときに、
top
やleft
などを%で指定していると、使っている機種によって%の値が変わってきます。これは厄介。。。
こんな時に役立つのが、Javascriptを使ってページトップからの高さを取得してしまえば、機種によって%の値を変える必要はありません!
結論から言うと、
getBoundingClientRect()
、pageYOffset
の2つの関数を使います。それでは使い方を見ていきましょう!!
要素を取得
index.jsconst topToElement = document.getElementsByClassName('class-name')[0]また、
document.getElementId
などで取得してくださいページトップからの高さを取得
index.jsconst topToElement = document.getElementsByClassName('class-name')[0] const topToElementHeight = topToElement.getBoundingClientRect().top + window.pageYOffset console.log(topToElementHeight)このようにして高さを取得することができます!
また、これらはVue.jsで使う場合、DOM要素と紐づけられた後の
mounted
で行ってください。
created
では取得できないのでご了承ください。以上、「ページトップからある要素までの高さの取得方法」でした!
良かったら、LGTM、コメントお願いします。
また、何か間違っていることがあればご指摘頂けると幸いです。
他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!
Thank you for reading
- 投稿日:2021-01-18T08:49:47+09:00
困っている方必見!offsetTopで高さが取得できない時の対処法
cssにてpositionを使っているときに、
top
やleft
などを%で指定していると、使っている機種によって%の値が変わってきます。これは厄介。。。
こんな時に役立つのが、Javascriptを使ってページトップからの高さを取得してしまえば、機種によって%の値を変える必要はありません!
結論から言うと、
getBoundingClientRect()
、pageYOffset
の2つの関数を使います。それでは使い方を見ていきましょう!!
※注意 要素の高さは普通offsetTopで取得できます。ただ、親要素に
position:relative
が設定してあると取得できない場合があるので、今回はそのやり方でやっていきます。要素を取得
index.jsconst topToElement = document.getElementsByClassName('class-name')[0]また、
document.getElementId
などで取得してくださいページトップからの高さを取得
index.jsconst topToElement = document.getElementsByClassName('class-name')[0] const topToElementHeight = topToElement.getBoundingClientRect().top + window.pageYOffset console.log(topToElementHeight)このようにして高さを取得することができます!
また、これらはVue.jsで使う場合、DOM要素と紐づけられた後の
mounted
で行ってください。
created
では取得できないのでご了承ください。以上、「ページトップからある要素までの高さの取得方法」でした!
良かったら、LGTM、コメントお願いします。
また、何か間違っていることがあればご指摘頂けると幸いです。
他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!
Thank you for reading
- 投稿日:2021-01-18T08:19:18+09:00
一時的
main.vue<template> <div class="hello"> </div> </template> <script> export default { data(){ return { addMembers: [], renewMembers: [], oldMembers : [ {teamName: "team1", memberName: "tanaka", family: [{father: "namihei", sex: "man"}, {mothor: "hune", sex: "female"}], bio: {type: "A", tall: "small"}}, {teamName: "team2", memberName: "yamada", family: [{father: "tusbasa", sex: "man"},{mothor: "shizuka", sex: "female"}], bio: {type: "B", tall: "small"}}, {teamName: "team3", memberName: "ueno", family: [{father: "nobita", sex: "man"}, {mothor: "mama", sex: "female"}], bio: {type: "AB", tall: "tall"}}, ], newMembers : [ {teamName: "team1", memberName: "tanaka", family: [{mothor: "hune", sex: "female"}, {father: "namihei", sex: "man"}], bio: {type: "A", tall: "small"}}, {teamName: "team2", memberName: "yamada", family: [{father: "tusbasa", sex: "man"}, {mothor: "shizuka", sex: "female"}], bio: {type: "B", tall: "small"}}, {teamName: "team3", memberName: "ueno", family: [{father: "nobita", sex: "man"}, {mothor: "mama", sex: "female"}], bio: {type: "AB", tall: "tall"}}, {teamName: "team4", memberName: "uesugi", family: [{father: "hideo", sex: "man"}, {mothor: "kera", sex: "female"}], bio: {type: "AB", tall: "small"}} ] } }, created(){ this.mainProcess() }, methods: { CheckObjectBio: function (newMember, oldMember) { // 変更前のメンバー情報を文字列に変換 var strOldMember = JSON.stringify(oldMember); if (strOldMember.indexOf(JSON.stringify(newMember)) < 0) { return true } else { return false } }, CheckObjectFamily: function(newMember, oldMember) { // 変更前のメンバー情報を文字列に変換 var strOldMember = JSON.stringify(oldMember); // 変更後メンバーを文字列に変換して変更前メンバーとデータが一致するか確認 var test = newMember.filter(function (item) { // 一致しないデータがあった場合はtureを返す if (strOldMember.indexOf(JSON.stringify(item)) < 0) { return true } else { return false } }).length > 0 return test }, compareMember: function(newMember, oldMember, renewList){ if (newMember.memberName != oldMember.memberName){ renewList.push([newMember, oldMember]) } if (this.CheckObjectFamily(newMember.family, oldMember.family)){ renewList.push([newMember, oldMember]) } if (this.CheckObjectBio(newMember.bio, oldMember.bio)){ renewList.push([newMember, oldMember]) } return renewList }, mainProcess: function(){ for (let newMember of this.newMembers){ newMember['newFlag'] = true loop:for (let oldMember of this.oldMembers){ if (newMember.teamName == oldMember.teamName){ newMember['newFlag'] = false // 更新比較処理 this.renewMembers = this.compareMember(newMember, oldMember, this.renewMembers) break loop; } } } for (let newMember of this.newMembers){ if (newMember['newFlag'] == true){ this.addMembers.push(newMember) } } console.log(this.renewMembers) console.log(this.addMembers) } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h3 { margin: 40px 0 0; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
- 投稿日:2021-01-18T00:11:45+09:00
え、意外とみんな知らない!?要素外でクリックしたときにイベントを発火させる方法
皆さんこんにちは!
今サイト制作を行っている際に、ふとドロップダウンメニュー(プルダウンとも呼ぶ)を作っていた時、「要素外でクリックしたときにメニューを閉じたいな~」と思い、1から構築しようとしたけどめちゃだるい!!!
僕がサイト制作を行うときに一番心掛けていることは、「どれだけ楽をして作るか」を日々考えながらやっています。
そんな僕にとって、この機能を1から作るなんて死んでもやりたくもない。。。
Googleで検索したところ、、、
なんとありました!!
パッケージ名は「vue-click-outside」
初めて聞いた
さて、今回はドロップダウンメニューを作りつつ「vue-click-outside」を使っていきたいと思います。
使い方だけ見たいという方は、こちらのサイトからご覧ください。
使い方の例も載っているので、分かりやすいかと。
それでは、順を追って一緒に使い方を見ていきましょう!
パッケージのインストール
npm i vue-click-outside --save-devドロップダウンメニューの作成(リストの作成)
ここからはドロップダウンメニューを作っていきます。
表示したいメニュー項目を
menuList
で定義し、isOpend
で要素をクリックしたかを判断します。また、menuList
のプロパティはお好みで設定してください。App.vue<script> export default{ data() { return { isOpend: false, menuList: [ { icon: 'user', id: 'account?isActive=0', labelText: 'アカウント情報' }, { icon: 'envelope', id: 'email?isActive=1', labelText: 'メールアドレス変更' }, { icon: 'key', id: 'password?isActive=2', labelText: 'パスワード変更' }, { icon: 'calendar-alt', id: 'event?isActive=3', labelText: 'イベント' }, { icon: 'user-minus', id: 'withdrawal?isActive=4', labelText: '退会' } ] } }, } </script>v-forでメニューリストを表示
次は、先ほど作成したオブジェクトを使用し、v-forを使って表示していきます。
また、ドロップダウンメニューを表示したときモーダルウィンドウとして表示するため、Buefyを使っていきます。アイコンもBuefyで表示します。
Buefyの使い方は、こちら以下の記事で詳しく書いているので、興味のある方はぜひご覧ください!
初心者必見!サイト制作は楽してなんぼ。CSSフレームワークBuefyの紹介!!
効率的にサイト作り!Buefyでアイコンを表示しよう!!App.vue<template> <div class="phone-side-menu"> <div class="drop-down-menu"> <div class="drop-down-menu-wrapper"> <b-modal v-model="isOpend"> <div class="drop-down-menu-list"> <ul> <li v-for="(element, index) in menuList" :key="index"> <input :id="element.id" name="sideMenuItems" type="radio" /> <label :for="element.id" class="phone-menu-label"> <b-icon pack="fas" :icon="element.icon" size="medium"></b-icon> {{ element.labelText }} </label> </li> </ul> </div> </b-modal> </div> </div> </div> </template> <script> export default{ data() { return { isOpend: false, menuList: [ { icon: 'user', id: 'account?isActive=0', labelText: 'アカウント情報' }, { icon: 'envelope', id: 'email?isActive=1', labelText: 'メールアドレス変更' }, { icon: 'key', id: 'password?isActive=2', labelText: 'パスワード変更' }, { icon: 'calendar-alt', id: 'event?isActive=3', labelText: 'イベント' }, { icon: 'user-minus', id: 'withdrawal?isActive=4', labelText: '退会' } ] } }, } </script>モーダルウィンドウの表示
次は、クリックされたときにモーダルウィンドウを表示する関数、ボタンを作ります。
App.vue<template> <div class="phone-side-menu"> <div class="drop-down-menu"> <div class="drop-down-menu-wrapper"> <!-- ここから追加 --> <b-button type="is-text" @click="toggleMenuList"> ドロップダウンメニュー </b-button> <b-modal v-model="isOpend"> <div class="drop-down-menu-list"> <ul> <li v-for="(element, index) in menuList" :key="index"> <input :id="element.id" name="sideMenuItems" type="radio" /> <label :for="element.id" class="phone-menu-label"> <b-icon pack="fas" :icon="element.icon" size="medium"></b-icon> {{ element.labelText }} </label> </li> </ul> </div> </b-modal> </div> </div> </div> </template> <script> export default{ data() { return { isOpend: false, menuList: [ { icon: 'user', id: 'account?isActive=0', labelText: 'アカウント情報' }, { icon: 'envelope', id: 'email?isActive=1', labelText: 'メールアドレス変更' }, { icon: 'key', id: 'password?isActive=2', labelText: 'パスワード変更' }, { icon: 'calendar-alt', id: 'event?isActive=3', labelText: 'イベント' }, { icon: 'user-minus', id: 'withdrawal?isActive=4', labelText: '退会' } ] } }, methods: { toggleMenuList() { this.isOpend = !this.isOpend } } </script>ボタンをクリックしたら、
toggleMenuList
という関数を実行してモーダルウィンドウの表示・非表示を行います。要素外をクリックしたときの関数を作成
最後に、モーダルウィンドウを表示中に要素外をクリックしたら、モーダルウィンドウを閉じるための関数を作成していきます。
関数名は
hideMenuList
、先ほどインストールしたパッケージをインストールしscript内でdirectives
を定義、v-click-outside
でイベントの発火というような仕組みになっております。
App.vue<template> <!-- イベント発火 --> <div v-click-outside="hideMenuList" class="phone-side-menu"> <div class="drop-down-menu"> <div class="drop-down-menu-wrapper"> <!-- ここから追加 --> <b-button type="is-text" @click="toggleMenuList"> ドロップダウンメニュー </b-button> <b-modal v-model="isOpend"> <div class="drop-down-menu-list"> <ul> <li v-for="(element, index) in menuList" :key="index"> <input :id="element.id" name="sideMenuItems" type="radio" /> <label :for="element.id" class="phone-menu-label"> <b-icon pack="fas" :icon="element.icon" size="medium"></b-icon> {{ element.labelText }} </label> </li> </ul> </div> </b-modal> </div> </div> </div> </template> <script> export default{ // ディレクティブを定義 directives: { ClickOutside }, data() { return { isOpend: false, menuList: [ { icon: 'user', id: 'account?isActive=0', labelText: 'アカウント情報' }, { icon: 'envelope', id: 'email?isActive=1', labelText: 'メールアドレス変更' }, { icon: 'key', id: 'password?isActive=2', labelText: 'パスワード変更' }, { icon: 'calendar-alt', id: 'event?isActive=3', labelText: 'イベント' }, { icon: 'user-minus', id: 'withdrawal?isActive=4', labelText: '退会' } ] } }, methods: { toggleMenuList() { this.isOpend = !this.isOpend }, // 関数を定義 hideMenuList() { this.isOpend = false } } </script>いかがだったでしょうか?
このようにして、ドロップダウンメニューのモーダルウィンドウを表示、要素外をクリックしたらモーダルウィンドウを閉じるという一連の動作を完成させることができます!
最近、モチベが低下しつつある。。。
それでも僕は頑張ります!
皆さんも一緒に頑張りましょう!!!
以上、「え、意外とみんな知らない!?要素外でクリックしたときにイベントを発火させる方法」でした!
良かったら、LGTM、コメントお願いします。
また、何か間違っていることがあればご指摘頂けると幸いです。
他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい!!
Thank you for reading