- 投稿日:2020-10-14T23:52:29+09:00
【Firebase Authentication】Nuxt.jsで作成したアプリケーションにログイン機能をつける。
Nuxt.jsでのログイン実装
現在ユーザー機能が必要なアプリケーションを作成しているため,ログイン機能を実装する必要があります。
Firebase Authenticationの機能を使って登録したユーザーがログインできるかを確認します。前提
・Firebaseが使える状態にある
・axiosがインストール済みであるページ構成
よくあるヘッダーの右側にログイン、サインインがあるパターンを想定します。
こんな感じです。
まずはリンク先のページをpages配下に用意してあげましょう。
touch pages/login.vue
続いてヘッダーにリンクを用意してあげましょう。
Nuxtはルーティングが簡単にできるからとても便利ですね。header.vue<ul class="list-inline"> <li class="list-inline-item"><n-link to="/login">Log in</n-link></li> </ul>loginフォームを用意する
シンプルなフォームがほしかったためこちらからお借りしました。
https://codepen.io/colorlib/pen/rxddKy
Firebase Authenticationでユーザーを用意
1.Authenticationをクリック
2.ユーザーを追加をクリック
3.メールアドレスとパスワードを入力(存在しないもので構いません)
4.ユーザーを追加をクリックSign-in methodの設定
1.Sign-in methodをクリック
2.メール/パスワードを有効化
plugins/firebase.jsを用意
firebaseの情報を設定します。
1.プロジェクトの概要 > 歯車をクリック > プロジェクトを設定をクリック
2.全般をスクロールするこちらの画面をスクロールすると表示される情報ですね。
plugins/firebase.jsconst config = { apiKey: "{{ APIKEY }}", authDomain: "{{ AUTHDOMAIN }}", databaseURL: "{{ DATABASEURL }}", projectId: "{{ PROJECTID }}", storageBucket: "{{ STORAGEBUCKET }}", messagingSenderId: "{{ MESSAGINGSENDERID }}", appId: "{{ APPID }}", measurementId: "{{ MESUREMENTID }}" }; // Initialize Firebase if (!firebase.apps.length) { firebase.initializeApp(config); } export default firebase;storeを用意する
データを保存しておくという仕組みしか理解しておりませんので、提供いただいたコードをそのまま掲載します。
store/index.jsimport firebase from '~/plugins/firebase' // data保管庫 export const state = () => ({ user: { uid: '', email: '', login: false, }, }) // stateの情報を取得 export const getters = { user: state => { return state.user; } } // storeの上書き以外の処理や非同期通信 export const actions = { login({ dispatch }, payload) { // メールとパスワードでログイン console.log('login action'); firebase.auth().signInWithEmailAndPassword(payload.email, payload.password) .then(user => { console.log('ログイン成功!'); this.$router.replace({ path: '/' }); dispatch('checkLogin') }) .catch((error) => { alert(error); }) }, loginGoogle({ dispatch }) { // Googleアカウントでログイン console.log('loginGoogle action'); const provider = new firebase.auth.GoogleAuthProvider(); firebase.auth().signInWithPopup(provider) .then(result => { const user = result.user; console.log('googleログイン成功!'); dispatch('checkLogin'); }) .catch((error) => { alert(error); }); }, checkLogin({ commit }) { // ログインしているかどうかのチェックログインしていたらデータ追加 firebase.auth().onAuthStateChanged((user) => { console.log(user); if (user) { console.log(user); commit('login', { uid: user.uid, email: user.email }); } }) }, logout({ commit }) { // ログアウト firebase.auth().signOut() .then(() => { console.log("ログアウトしました"); commit('logout'); }) .catch((error) => { console.log(`ログアウト時にエラーが発生しました (${error})`); }); } } // stateの上書き(代入) export const mutations = { login(state, payload) { state.user.uid = payload.uid; state.user.email = payload.email; state.user.login = true; }, logout(state) { state.user.uid = ''; state.user.email = ''; state.user.login = false; } }ここまでで下準備が終わりました
login.vueから実処理を行うLoginMenuのコンポーネントを呼び出します
pages/login.vue<template> <div> <h1>Log In</h1> <LoginMenu /> <h3 v-if="user.login"> ログインしました </h3> <h3 class="title" v-else> ログインしてください </h3> </div> </template> <script> import LoginMenu from "@/components/loginMenu.vue"; export default { components: { LoginMenu: LoginMenu, }, computed: { user() { return this.$store.getters["user"]; }, } }; </script>components/loginMenu.vue<template> <div class="login-page"> <div class="form"> <div class="register-form" v-if="this.$route.path === '/signup'"> <input type="text" placeholder="name"/> <input type="password" placeholder="password"/> <input type="text" placeholder="email address"/> <button>create</button> <p class="message">Already registered? <n-link to="/login">Sign In</n-link></p> </div> <div class="login-form" v-else> <input type="text" v-model="email" placeholder="username"/> <input type="password" v-model="password" placeholder="password"/> <button v-on:click="login">login</button> <p class="message">Not registered? <n-link to="/signup">Create an account</n-link></p> </div> </div> </div> </template> <script> export default { computed: { // dataのように扱える // dataを作る前処理が必要な際に利用 user () { return this.$store.getters['user']; }, }, data () { return { email: '', password: '', } }, mounted() { // ログインしているかどうかのチェックログインしていたらデータ追加 this.$store.dispatch('checkLogin'); }, methods : { async login () { // メールとパスワードでログイン console.log('login action', this.email, this.password); this.$store.dispatch('login', {email:this.email, password:this.password}); }, loginGoogle() { // Googleアカウントでログイン this.$store.dispatch('loginGoogle'); }, logout : function() { // ログアウト this.$store.dispatch('logout'); } } } </script>ログイン可能か確認する
ひとまずログインを行うと右のメニューがlogoutになるか確認します。
header.vue<template> <nav class="navbar navbar-light bg-light"> <h1><n-link to="/">title</n-link></h1> <ul class="list-inline" v-if="user.login"> <li class="list-inline-item"><n-link to="/logout" >Log Out</n-link></li> </ul> <ul class="list-inline" v-else> <li class="list-inline-item"><n-link to="/login">Log in</n-link></li> <li class="list-inline-item"><n-link to="/signup">Sign up</n-link></li> </ul> </nav> </template>nuxt.jsとFirebase Authenticationでログインフォームからログイン#protoout pic.twitter.com/rDzU3q17P6
— ウーリズム (@Uh_rhythm) October 14, 2020ひとまず作りながら覚えていく
Nuxt.jsは以前から何度か触れていましたが複数ページにまたがる物を作るのは今回が初めてだったため
作りながら覚えていくことになります。
ひとまずstoreやstateについて早急に学んでいく必要がありますね。
- 投稿日:2020-10-14T21:52:58+09:00
Vue-Laravel→Heroku 実践ミニマル必要情報
私のスタイル
初めまして。翁と申します。
ミニマルで強迫観念やストレスなく、かつ最大限を提供する
"Huge Minimalism"
を提唱し、スタイルとして活動させていただいてます。
お手柔らかによろしくお願いいたします。あくまで"より高みへ。"を意識しており
一記事執筆5分以内と制限しております。
ご理解いただけたらと思います。デプロイまで
1.ローカルコミット
git init git add . git commit -m "first commit"//ここで行うことで自動でデプロイ先が設定されます。 heroku create2.デプロイ
//行く先確認 >git remote -v heroku https://git.heroku.com/~~.git (fetch) heroku https://git.heroku.com/~~.git (push)//Herokuにデプロイ git push heroku master//App keyを設定する。 //これをする前はアクセスしても500エラーになるはず >php artisan --no-ansi key:generate --show >heroku config:set APP_KEY="一つ上の結果"//Githubへと //originを設定 >git remote add origin https://github.com/~~/~~.git //行く先確認 >git remote -v heroku https://git.heroku.com/~~.git (fetch) heroku https://git.heroku.com/~~.git (push) origin https://github.com/~~/~~.git (fetch) origin https://github.com/~~/~~.git (push) //デプロイ >git push origin master
- 投稿日:2020-10-14T21:52:58+09:00
Vue-Laravel→Heroku -デプロイまで-
私のスタイル
初めまして。翁と申します。
ミニマルで強迫観念やストレスなく、かつ最大限を提供する
"Huge Minimalism"
を提唱し、スタイルとして活動させていただいてます。
お手柔らかによろしくお願いいたします。あくまで"より高みへ。"を意識しており
一記事執筆5分以内と制限しております。ご理解いただけたらと思います。デプロイまで
1.ローカルコミット
基本ルートディレクトリでコマンドを打っていきます。
```git init
git add .
git commit -m "first commit"
```//ここで行うことで自動でデプロイ先が設定されます。 >heroku create.git/config[remote "heroku"] url = https://git.heroku.com/okinaofficial.git fetch = +refs/heads/*:refs/remotes/heroku/*2.デプロイ
//行く先確認 >git remote -v heroku https://git.heroku.com/~~.git (fetch) heroku https://git.heroku.com/~~.git (push)//Herokuにデプロイ >git push heroku master//App keyを設定する。 //これをする前はアクセスしても500エラーになるはず >php artisan --no-ansi key:generate --show >heroku config:set APP_KEY="一つ上の結果"//Githubへと //originを設定 >git remote add origin https://github.com/~~/~~.git //行く先確認 >git remote -v heroku https://git.heroku.com/~~.git (fetch) heroku https://git.heroku.com/~~.git (push) origin https://github.com/~~/~~.git (fetch) origin https://github.com/~~/~~.git (push) //デプロイ >git push origin master
- 投稿日:2020-10-14T17:37:24+09:00
ヘッダー固定のリストコンポーネントの実装
始めに
以下のようなヘッダーを固定にした一覧を表示するコンポーネントを作った際に色々ハマったことがあるので備忘録として残したいと思います。
一番単純な実装
一番単純なのはheaderに
position: sticky;
をつけることです。stickyを使ったStickyListコンポーネント<template lang="pug"> .sticky-list .sticky-list__header slot(name="header") .sticky-list__content slot(name="content") </template> <style lang="scss" scoped> .sticky-list { position: relative; width: 100%; height: 100%; overflow-y: auto; &__header { position: sticky; top: 0; left: 0; } } </style>呼び出しがわは以下のような感じでやると一番最初に表示したGIFアニメのようなものができます。
呼び出し側<template lang="pug"> StickyList template(v-slot:header) .header .header__column.-item1 番号 .header__column.-item2 項目2 .header__column.-item3 項目3 template(v-slot:content) .content template(v-for="index in 30") content__item .content__item__column.-item1 {{ index }} .content__item__column.-item2 内容2 .content__item__column.-item3 内容3 </template> <style lang="scss" scoped> // 各カラム幅はmixinで設定しておく @mixin list-width() { &.-item1 { flex: 0 0 50px; } &.-item2 { flex: 1 1 0; } &.-item3 { flex: 2 2 0; } } .header { display: flex; padding: 10px; background-color: #fff; border-bottom: solid 1px #ccc; &__column { @include list-width(); } } .content { &__item { display: flex; padding: 10px; & + & { border-top: solid 1px #ccc; } &__column { @include list-width(); } } } </style>問題点
基本的にはこれで問題ないですが、親要素がflexを使っている場合、iOS Safariだと上手くいかない場合があるようです?
サンプルコード
サンプルコードは以下になります。CodePenではVueファイルは書けないので別な書き方になっていますが基本は同じです。
See the Pen StickyList(stickyで実装) by wintyo (@wintyo) on CodePen.
flexで書いたパターンも用意していますので、iPhoneがある方はこちらから動作を確認してみると上手く動いていないことが分かると思います。
https://codepen.io/wintyo/full/xxOwBbBコンテンツ内だけスクロールさせる
前項のやり方では上手くいかない時があるので、愚直にコンテンツ内だけスクロールするようなコンポーネントにしてみます。
この際にコンテンツ側だけスクロールバーが出てしまうため、その幅分ヘッダーにpaddingを入れて幅を合わせます。コンテンツ内だけスクロールさせる<template lang="pug"> .sticky-list .sticky-list__header( :style="{ paddingRight: `${$data.scrollBarWidth}px` }" ) slot(name="header") .sticky-list__content( ref="elContent" ) slot(name="content") </template> <script> export default Vue.extend({ data() { return { scrollBarWidth: 0, }; }, mounted() { const { elContent } = this.$refs; // スクロールバーの幅を計算する this.$data.scrollBarWidth = elContent.offsetWidth - elContent.clientWidth; } }); </script> <style lang="scss" scoped> .sticky-list { display: flex; flex-direction: column; height: 100%; overflow: hidden; &__content { flex: 1 1 0; overflow-x: hidden; overflow-y: scroll; } } </style>実行すると以下のようなGIFアニメになります。
サンプルコード
このやり方のサンプルコードは以下になります。
See the Pen Sticky List(paddingで実装) by wintyo (@wintyo) on CodePen.
終わりに
以上がヘッダー固定のリストコンポーネントの実装でした。基本的には
position: sticky
で済ませられるならそれにしたいですが、意外と罠がありましたので、確実にやる場合は2つ目のやり方を参考にするといいと思います。
- 投稿日:2020-10-14T15:17:11+09:00
vue ui (vue cli 3~) で作ったプロジェクトで eslint を無効化する
vue ui でのプロジェクト作成時に入れた eslint を無効化したくなったが、出来るようになるまで時間がかかったのでメモ。
環境
@vue/cli 4.5.7プロジェクト内でwebpackの設定を記述している箇所が見当たらない
-> 初期状態では vue-cli の内部的な設定を利用している(?)ためファイルが存在しない
下は設定の中身を確認するコマンドvue inspect vue inspect > output.js // ファイルに出力する参考 https://cli.vuejs.org/guide/webpack.html#inspecting-the-project-s-webpack-config
eslint を無効化したい
-> vue.config.js に記載した内容がデフォルトのwebpack設定にマージされる
下の内容のファイルをプロジェクトルートに作成するvue.config.jsmodule.exports = { chainWebpack: config => { config.module.rules.delete('eslint'); } }参考 https://stackoverflow.com/questions/49121110/how-to-disable-eslint-on-vue-cli-3
- 投稿日:2020-10-14T12:06:06+09:00
(3)VueによるReactiveプログラミング その1
Vueを使って簡単なプログラムを作成して、特にリアクティブなUIの基本的な動作を確認してみたいと思います。
参考ドキュメント
リアクティブプログラミング
今までのリアクティブではないプログラミングでは、例えば、テキストの入力を受け付けて、その入力文字列を表示するには、何らかのイベント(ボタンの押下)をきっかけに、入力値の変数への格納と画面の表示を同時に変更する、というものでした。
これに対し、リアクティブなプログラミングでは、データとUIが密接に繋がっていて、プログラムの変数の値が変更されたら、画面にはその値が自動的にに表示される、というような動きをします。そのため、開発者は、プログラムで保持している値だけに注意してプログラミングすればよく、コードの量も少なくなることが期待できます。Vue+Vuetifyのプロジェクトを作成
> vue create react01
> cd react01
> vue add vuetify
全て、Defaultを選択してプロジェクトを作成します。
src/components/HelloWorld.vue を使ってVueの動作を確認しようと思います。
最初に、HeeloWorld.vueの必要な物(<template> <v-container> <script>
)だけを残して、あとは全部削除してしまいます。削除すると、下のようになります。これで、Terminalから、
> npm run serve
でローカルのサーバを起動し、さらに、デバッガーからブラウザを起動すると、App.vueにある、上部のバー(
<v-app-bar>
)だけが残った状態になるはずです。ここで、HelloWorld.vueファイルの、
<template>...</template>
の部分は、主に画面のUIをHTMLベースで記述した部分になり、<script>...</script>
は、処理をJavaScriptで記述する部分になっています。
全体の動きを少し説明すると、Vueのアプリケーションがブラウザに読み込まれると、まず、main.jsが動作し、その中でApp.vueが読み込まれ、次にApp.vueにある<template>
中の、<HelloWorld/>
で、HelloWorld.vueが呼び出される、というように動いています。inputフィールドの作成
次は、Vuetifyにある、テキストフィールド
<v-text-field>
を使って、入力した内容が画面にリアルタイムに表示されるプログラムを上記の画面に追加しようと思います。HelloWorld.vueを以下のように変更します。Visual Studio CodeのTerminalで実行しているローカルサーバはそのまま実行したままで構いません。
<template> <v-container> {{ message }} <v-text-field v-model="message" /> </v-container> </template> <script> export default { name: "HelloWorld", data: function () { return { message: '' } } }; </script>変更したファイルを保存すると、自動的に再コンパイルされ、ブラウザ情は、以下のような画面になります。
ラインが表示されている入力のフィールドに文字を入力すると、それにしたがって、上部に同じ文字が表示されるのがわかると思います。
ここで、
<v-text-field>
のタグの中にある、v-model
とあるプロパティで指定されているのが、リアクティブに反応する変数です。この変数を、<script>
のdata
の部分に記述することで、このmessage
という変数が、Vueで管理されるようになります。
さらに、{{message}}
を<template>
の<v-container>
の中に記述すると、その変数の中身を表示することができるようになります。テキストフィールドをかっこよくする
テキストフィールドは、様々なプロパティを設定することで、簡単にプロダクトレベルのUIに仕上げることができます。
<v-text-field>
を以下のようにして確認します。<v-text-field label="Input your message here." prepend-icon="mdi-message-text-outline" v-model="message" />そうすると、テキストフィールドの前にアイコンが表示され、また、テキストフィールドにlabelに設定した文字が表示されます。入力を始めると小さなフォントでテキストフィールドの上部に表示されるのがわかるかと思います。
アイコンは、マテリアルデザインのアイコンのリストから、検索して選ぶことができます。表示されるアイコンの名前の前に、
mdi-
をつけて、prepend-icon
に設定するだけです。おまけ1 nameは必要?
"HelloWorld.vue"の中で指定されているnameは、必ずしも必要ありません。nameは、Vueが必要なコンポーネントを探すときのキーになりますが、.vueファイルに記述されている場合は、自動的にファイル名がnameに設定されるためです。
おまけ2 リアクティブな動作はどうやって実装されているのか
変数に格納されているデータが変更されると、どのような仕組みを使って関連する変数が変更されたり、処理が動いたりできるのでしょうか。
それについては、Vueのガイドや、この記事が参考になると思います。簡単に説明すると、ES5から追加された、Object.defineProperty を使って、変数の読み出しをフックして、変数の値が変更された時に実行すべき処理の依存関係を登録し、いざ変更されたときにそれらの処理を実行する、ということを行っています。
おまけ3 アロー関数
JavaScriptのfunctionの書き方は、ES6からアロー関数
=>
で記述することができるようになっています。単純に全体として短くなりますし、returnを省略できたり、条件によってかっこや波括弧を省略できたりするので、すっきり書くことができます。ただ、functionで宣言された関数と、アロー関数の中とでは、this
の参照の仕様が変わっているので注意が必要です。thisの参照については、こちらの記事やこちらの記事が参考になると思います。参考までに、functionキーワードを使って書くと
export default { name: "HelloWorld", data: function () { return { message: '' } } };ですが、アロー関数を使って以下のように書くこともできます。
export default { name: "HelloWorld", data: () => ({ message: '' }) };
- 投稿日:2020-10-14T12:05:02+09:00
(2)Vue + Vuetify をVisual Studio Codeで実行・デバッグ
Vue, Vuetifyがインストールされていない場合は、前の記事(Vue + Vuetifyでローカル開発環境をセットアップ)を参照しながら、Node.js, Vue, Vue CLI, Vuetifyのインストールをしてください。
この記事中のスクリーンショットはMacOSのものですが、Visual Studio CodeのTerminalを使えば、操作はほぼ同じです。
以下に入る前に、Visual Studio Codeをダウンロードしインストールしておいてください。Debug環境の設定
まず、Visual Studio Codeで、Vueのソースコードに対して、ブレークポイントを設定し、ステップ実行しながらデバッグができることを確認します。
- Visual Studio Codeを起動し、Fileメニューから"New Window"を選択してWorkspaceを作る。
- Welcomeと表示されたページの、左側にある、Startの"Open Folder..."を選択するか、Fileメニューから"Add folder to workspace..."を選択し、前の記事で作成した、"test002"のフォルダーをWorkspaceに追加する。
- Debugの設定をするために、左側のデバッグボタンを押し、"create a launch.json file"を選択。Select Environment...で"Chrome"を選択。
- ファイルの作成場所を、workspaceに作成するかlaunch.jsonファイルを別途作成するかを聞かれる場合もあります。どちらでも構いませんが、ここでは、launch.jsonファイルを作成しました。これによって、test002/.vscode/launch.jsonファイルが作成されます。
Terminalでローカルのサーバを起動し、Debug開始
- Terminalメニューから"New Terminal..."を選択すると、下にshellあるいは、コマンドプロンプトが表示されます。作業ディレクトリは、test002になっているはずなので、ここで、
> npm run serve
と入力すると、開発用のローカルサーバが起動します。
- ローカルサーバが起動したことを確認して、左上の三角のボタンを押して、デバッグの開始をします。
- Chromeが起動して、自動的に localhost:8080に接続された状態になります。
- 停止するには、表示されているフロートメニューの停止を押します。
ステップ実行
デバッグには、ソースコード上でブレークポイントを設定し、ステップ実行が有効ですが、この環境でできるか確認してみましょう。
- main.jsファイルを選択して、ブレークポイントを設定します。ブレークポイントは、ソースコードの頭をクリックすると設定できます。ここでは、main.js内の、"Vue.config.productionTip = false"という行の頭をクリックします。赤い印がつけば、ブレークポイントが設定できています。
- 再度、左側のデバッグボタンを押し、左上の三角のボタンから、デバッガを起動すると、以下のように、ブレークポイントで停止した状態になることが確認できます。
- さっきのフローティングメニューから、ステップ実行、ステップイン、実行を続ける、などを選択してデバッグを行うことができます。
- ローカルのサーバを停止するには、Visual Studio Codeを終了するか、Terminalで、Cntl+C を入力すれば、サーバは停止します。
workspaceの作成
- 最後に、Visual Studio Codeのworkspaceを保存します。Fileメニューから、"Save Workspace As..."を選択します。
- test002ディレクトリに、"test002.code-workspace"として、保存します。
- WorkspaceファイルをGitの管理から除くために、".gitignore"ファイルを選択して、最後の行に、*.code-workspaceを追加しておきます。
まとめ
この記事では、Visual Studio Codeから、ローカルでサーバを起動し、Vueのアプリケーションの実行、ブレークポイントの設定ができることを確認しました。
- 投稿日:2020-10-14T11:39:37+09:00
【Vue.js】 axios / firebaseを利用して、データのやり取り
【ゴール】
axios / firebaseを利用して、データのやり取り
【環境】
mac catarina 10.156
Vue.js v2.6.12
【実装】
firebaseのセットアップ
下記URLにアクセス、googleアカウントの登録、作成
https://firebase.google.com/1 プロジェクト作成
2 アナリティクスはOFFで構いません。
3 cloud firestroeにてdatabaseの作成
4 テストモードで構いません
5 ロケーションはデフォルトのままで構いません
6 作成完了
7 左のメニューバーの設定→プロジェクトの設定→プロジェクトIDを確認
axiosのインストール
※ワークスペース作成は割愛
Mac.terminal$ npm install axiosコード
<template>内
※「@click="textSend"」でaxiosが発火(下記に詳細ページ貼ってます)
※「v-for」で繰り返し処理で表示App.vue<template> <div> <h2>Post,new</h2> <div> <div class="form"> <textarea name="text" cols="100" rows="10" v-model="text"></textarea ><br /> <button @click="textSend">send</button> </div> </div> <div v-for="post in posts" :key="post.text"> {{ post.fields.text.stringValue }} </div> </div> </template>
<script>内
※「import axios from "axios";」でaxioをインポート
※「created」でページ読み込みじにデータベースから情報を取得
※「posts」に取得したデータを配列として渡す
※「stringValue」はデータ型、指定してあげる
※「this.text = '';」でtextarea内を空にするapp.jsimport axios from "axios"; export default { data() { return { text: "", posts: [], }; }, created() { axios .get( "https://firestore.googleapis.com/v1/projects/texposts/databases/(default)/documents/text" ) .then((res) => { this.posts = res.data.documents; console.log(res); }); }, methods: { textSend() { axios .post( "https://firestore.googleapis.com/v1/projects/7番のプロジェクトID/databases/(default)/documents/text", { fields: { text: { stringValue: this.text, }, }, } ) .then((res) => { console.log(res); }); this.text = ""; }, }, }; </script>【まとめ】
■firebaseをセットアップ
■axiosをインストールしてhttp通信を可能に
■記述。URL等のタイポに気を付ける【オススメ記事】
■ 【Vue.js】 IF文・For文 条件分岐、繰り返し処理
https://qiita.com/tanaka-yu3/items/0ccf9a11525331b764de■【Vue.js】クリック処理 @click
https://qiita.com/tanaka-yu3/items/e578cadf35a7bc024770■ 【Vue.js】Vue.jsでfontawsome(Free版)を使用する方法
https://qiita.com/tanaka-yu3/items/86d05241f72674d186f6
- 投稿日:2020-10-14T10:26:20+09:00
Vue.jsの概念
Vue.jsは、インタラクティブな(双方向性の)UIを構築するためのJavaScriptのフレームワーク。
MVVMモデルの設計思考(ソフトウェアアーキテクチャ)を採用している。
コンポーネント指向のUIを設計することができる。MVVMモデルとは?
MVVMモデルとは、プログラムの処理を以下の3つの役割に分類して開発するモデル。
- Model
- View
- ViewModel
それぞれの頭文字を取ってMVVMモデルと呼ばれる。
基礎的なアーキテクチャであるMVC、及びViewとModelについてはこちらを参照。ViewModel
ViewModelは、ModelとViewを紐付ける接着剤の役割。
- Viewからリクエストを受ける
- ViewModelにリクエストが反映される(ViewModelのデータが書き換えられる)
- Modelに処理を命令
- 書き換えられた値をViewに反映
という処理を行う。値の変更が即時的にViewに反映されるのが特徴である。脊髄反射的なイメージ。
データバインディング
MVVMモデルを支えるのが、データバインディングである。
データバインディングとはデータをバインド(結びつける)ことで、ViewとViewModelを結びつけることである。
データバインディングは、ViewとView Modelどちらかの値が変化するたびにViewとView Model、両方の値が変更される。これが「データが双方向性を持って反映されるUI」を構築するVue.jsの最大の特徴である。
コンポーネント指向とは?
コンポーネント(Component)とは、部品という意味である。
コンポーネント指向とは、様々な機能をそれぞれ1つのコンポーネントとして切り出し、複数のコンポーネントを組み合わせることで、1つのサービス、アプリケーション、WEBサイトなどを作り上げる考え方である。
サービスをガンプラとすれば、コンポーネントは1つ1つのパーツである。ガンプラを組み立てるようにサービスを作り上げるのがコンポーネント指向である。
メリット
- 設計・開発・テストなどがコンポーネント単位でできる
- パーツを共通化することで、複数ページに渡る同じような実装を1つのコンポーネントで対応することができる
デメリット
- 表示されるページ数に対して必要なファイル数が多くなる
- コンポーネントが共通化されている場合、1つのコンポーネントを変更すると別のページで不具合が発生する可能性がある
参考
- 投稿日:2020-10-14T09:35:49+09:00
[Vue.js]自前でv-forとv-ifを同時に利用しないスライダーを実装する
この記事で書くこと
ソースの公開。
この記事を書く理由
Nuxtでアプリケーションを作成している時に、「スライダーを実装したいけど、モジュールを入れるほどじゃない、、」と思った時、いくつか記事をみたのですが、以下のように実装されているものが多かったです。
<div> <transition :name="slider"> <div :key="idx" v-for="(content, idx) in contents" v-if="content.id== idx"/> // 中身 </div> </transition> </div>この実装は、うまく表示されますが、一つ問題があります。それは、v-ifとv-forを同時に使用していることです。
Vue.jsのドキュメントにあるように、これは非推奨となっています。(Vue.jsドキュメント)
なので、タイトル通り、v-forとv-ifを同時に利用しないスライダーを実装してみました。ソース
See the Pen vue-slider by RyoTa (@RyoTa0222) on CodePen.
改良の余地等あるかもしれません。コメントいただければ幸いです!
- 投稿日:2020-10-14T04:23:35+09:00
vue.jsでvue-routerを使ってみる
初めて投稿をすることにしました、プログラミング歴7ヶ月目のKeitaです!
現在vue.jsを主に勉強しており、その中で特に便利だなと感じた機能を紹介していきたいと考えています。vue-router
今回紹介したいパッケージはvue-routerについてです。
vue.jsでvue-routerを使うと、仮想DOMのお陰で高速な画面遷移を行うことが可能になります。
設定も簡単に出来ますので、是非取り入れましょう。開発環境
- vue 2.6.11
- vueCli 4.5.6
- Node.js 14.4.0
- npm 6.14.5
です。
実際のフォルダ構造。
App.vue内にHeader.vueをimportし、常に固定されている状態を作ります。またHeader.vue componentの下で画面を切り替えていきたいと思います。
src ├── App.vue ├── component │ ├── Content.vue │ ├── ContentTwo.vue │ ├── ContentThree.vue │ └── Header.vue ├── main.js └── routes.jsインストール
では実際にインストールをしてみましょう!
1.<script src="/path/to/vue.js"></script>2.npm install vue-routerこの2つの内どちらかで設定します。1の場合は、そのままHTML内に貼り付け、2の場合は各自のterminal内でダウンロードします。
実際にコードを書いてみる
実際にvue-routerのパッケージを使えるようにするためには、src内のroutes.jsのファイルを作りmain.js内でroutes.jsをimportしmountします。
routes.jsを書く
実際に表示させたいcomponentにpathとname付けを行います。
exportを行って宣言させる事でmain.jsからimportを可能にさせます。要は、他のファイル内でも自由に使えるようにしたよって事です。routes.jsimport Content from './component/Content.vue'; import ContentTwo from './component/ContentTwo.vue'; import ContentThree from './component/ContentThree.vue'; export const routes = [ {path:'/',component:Content,name:'content'}, {path:'/Two',component:ContentTwo,name:'contentTwo'}, {path:'/Three',component:ContentThree,name:'contentThree'}, ]main.jsを書く
先程作成したroutes.jsとVueRouterをimportします。routes.jsに記述しただけでは何も行われません。
そこでVue.use()とnew Vue()内でダウンロードしたパッケージを使う宣言を行います。他のパッケージを使う際にも毎回書くので必ず忘れないように書きます。(私は何回も書くのを忘れてしまった事があります。汗)modeはhistoryにします。hashに設定するとhistoryより実行速度が早いとされていますが、使った事がないのでここではhistoryにします。
main.jsimport Vue from 'vue' import App from './App.vue' import {routes} from './routes' import VueRouter from 'vue-router' Vue.config.productionTip = false Vue.use(VueRouter) const router = new VueRouter({ made:'history', routes }) new Vue({ el: '#app', router, render: h => h(App) })これで概ね準備は完了です!ただ、肝心な画面を実際に切り替えて表示させなくてはいけませんよね。次は、router-linkとrouter-viewを使います。
router-linkとrouter-view
先ずApp.vueに移動しHeader.vueをimportします。その下にrouter-viewで表示させたい場所決めをしましょう。今回は画面の真ん中に文字をそれぞれ表示させたいと思います。
App.vue<template> <div class="container"> <Header /> <div class="view"> <router-view /> </div> </div> </template> <script> import Header from './component/Header.vue'; export default { components:{ Header, } } </script> <style> *{ margin: 0; padding: 0; } .view{ display: flex; align-items: center; justify-content: center; min-height: 100vh; font-size: 30px; } </style>HTMLで書く場合はaタグでリンク先に飛ぶ事が出来るようになりますが、vue-routerではrouter-linkタグを使います。名前の通り、リンク先に飛ぶ役割をしています。
そして、routes.jsで作ったpathをrouter-link内でto=""を用いてそれぞれのリンクに当てはめます。Header.vue<template> <div class="row"> <ul> <li><router-link to="/" exact><a href="#">Content</a></router-link></li> <li><router-link to="/Two" exact><a href="#">ContentTwo</a></router-link></li> <li><router-link to="/Three" exact><a href="#">ContentThree</a></router-link></li> </ul> </div> </template> <script> export default { } </script> <style scoped> *{ margin: 0; padding: 0; } .row{ width: 100%; height: 10vh; } ul{ width: 100%; list-style: none; display: flex; justify-content: start; } li{ display: flex; padding: 40px; } a{ text-align: center; font-size: 20px; color: rgb(7, 7, 7); width: 120px; height: 30px; text-decoration: none; cursor: pointer; margin: 0px 10px; } a:hover{ color: rgb(8, 126, 204); } .router-link-active{ border-bottom:2px solid rgb(10, 10, 10); color: rgb(5, 13, 117); width: 100%; } </style>nameを付けている場合は、toの前に:を付ける事で任意で値を受け渡す事が出来るようになります。propsと同じ用法ですね。
Header.vue<template> <div class="row"> <ul> <li><router-link :to="{name: 'content'}" exact><a href="#">Content</a></router-link></li> <li><router-link :to="{name: 'contentTwo'}" exact><a href="#">ContentTwo</a></router-link></li> <li><router-link :to="{name: 'contentThree'}" exact><a href="#">ContentThree</a></router-link></li> </ul> </div> </template> <script> export default { } </script> <style scoped> *{ margin: 0; padding: 0; } .row{ width: 100%; height: 10vh; } ul{ width: 100%; list-style: none; display: flex; justify-content: start; } li{ display: flex; padding: 40px; } a{ text-align: center; font-size: 20px; color: rgb(7, 7, 7); width: 120px; height: 30px; text-decoration: none; cursor: pointer; margin: 0px 10px; } a:hover{ color: rgb(8, 126, 204); } .router-link-active{ border-bottom:2px solid rgb(10, 10, 10); color: rgb(5, 13, 117); width: 100%; } </style>上記のHeader.vue内に書かれている様に、router-linkタグ内にexactを用いcssで色を設定すると、アクティブなリンク(今いるリンク内)を表示する事も出来ます。
router-view内では、router-linkで指定したリンク先の内容が表示されます。
Content.vue<template> <div> <p>Hello!</p> </div> </template> <script> export default { } </script> <style scoped> </style>ContentTwo.vue<template> <div> <p>Guten morgen!</p> </div> </template> <script> export default { } </script> <style scoped> </style>ContentThree.vue<template> <div> <p>Ciao!</p> </div> </template> <script> export default { } </script> <style scoped> </style>実際の画面
これで基本設定は終了です!次回はparamやpushを利用してvue-routerで出来る事を増やしていきたいと思います。
- 投稿日:2020-10-14T00:31:25+09:00
headers に独自のキーを追加してリクエストを送る
0. 環境
nginx:1.18.0
vue.js:2.6.121. 概要
ALB + ec2(nginx+gunicorn+flask) の構成でデプロイし、ALBにてリクエストヘッダーを確認し、アクセス制限をかけるのがゴールでした。UI側は cloudfront + s3 でデプロイ済みで、ここからサーバーにリクエストを送ります。
リクエストを送る際に cors のエラーが発生し、解決に時間がかかってしまったので、備忘録として書いておきます。
- 発生したエラー
Access to XMLHttpRequest at 'http://xxx.xxx.elb.amazonaws.com/yyy' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.2. 結論
nginx の設定(confファイル)に
Preflight Request
に対する設定を記述する。location / { # preflightに対するレスポンス指定 if ($request_method = 'OPTIONS') { add_header Access-Control-Allow-Origin '*'; # corsの許可 add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE'; # メソッドの許可 add_header Access-Control-Allow-Headers 'Origin, Authorization, Accept, Content-Type, key'; # ここにヘッダーに追加するキーを追加する! add_header Access-Control-Max-Age 3600; ...3. 各種設定・コードの確認
3.1 ALBの設定
ALB ではヘッダーに
key=value
が含まれている場合は、ec2に転送する設定。
3.2 UI(vue.js)側のリクエストコード
ヘッダーに
key
を追加し、axios で ALB に GETリクエストを送信。vue.jslet config = { headers: { 'key': 'value' }, }; this.axios .get('http://xxx.xxx.elb.amazonaws.com/hello', config) .then((response) => { console.log(response) ...4. ハマった点・解決方法
① CORS のリクエストは
Simple Request
とPreflight Request
の2種類に分けられる。Preflight Request
の場合、サーバー側で許可する設定が必要
② リクエストヘッダーに独自のヘッダーを追加する場合(今回のケースだとkey
)は、サーバー側でそれを許可する設定が必要① の解決
これについてはこのサイトが大変参考になりました。
CORS(Cross-Origin Resource Sharing)について整理してみた以下の条件の全てに該当する場合、ブラウザはpreflightリクエストを送る必要がないと判断し、シンプルなリクエストを送信します。それ以外の場合は、preflightリクエストを送信します。
・ HTTPメソッドがGET, POST, HEADのいずれか
・ HTTPヘッダにAccept, Accept-Language, Content-Language, Content-Type以外のフィールドが含まれない
・ Content-Typeの値はapplication/x-www-form-urlencoded, multipart/form-data, text/plainのいずれか今回のケースだとリクエストヘッダーに
key
が入っているためPreflight Request
とみなされます。なおPreflight Request
のレスポンスには、アクセス許可するメソッドをレスポンスヘッダに含める必要があるようです(結論のコードAccess-Control-Allow-Methods
の部分)。② の解決
メソッドを許可したのと同様に、ヘッダーの許可も必要になります。
こちらのサイトには次のような記述があります。CORS セーフリストリクエストヘッダー, Accept, Accept-Language, Content-Language, Content-Type は常に許可されており、このヘッダーで列挙する必要はありません。
上記のヘッダー以外はデフォルトでは許可されていないようです。今回のケースでは
key
を許可したいので追加します(結論のコードAccess-Control-Allow-Headers
の部分)。5. 感想
CORSについてあまり理解していなかったので、解決にかなり時間を費やしてしまいました。
間違っている点、補足等あればコメントを頂きたいです!参考
CORSまとめ
なんとなく CORS がわかる...はもう終わりにする。
CORS(Cross-Origin Resource Sharing)について整理してみた
MDN web docs
(ありがとうございました..)