- 投稿日:2019-08-29T23:44:20+09:00
初めてのvue.js 簡易的なメモ・備忘録編
はじめに
まず、私の説明だけ簡単にさせていただきます。
とあるベンチャー企業でフロントエンドエンジニアとして働いています。
ライブラリーはReactを使い、1年にも満たないですが、redux,redux-saga,非同期通信などなど、様々なことに挑戦して、Reactを自信を持って書けるようになりました。
そんな私が、あるきっかけでvue.jsを使用することになってので、勉強録としてまとめてみました。今回は、まとめというより、メモという意味合いが強いです。
vue.jsやフロントエンドに強い方、謝りや誤認識等ありましたら、ぜひご指摘ください!こちらの書籍をベースに学習しております。
Reactに馴染んでいる私にとって、非常にわかりやすく、スラスラ読める一冊です!
初めてプログラミングに触れた時は、全く理解できなかったが………
Vue.js入門 基礎から実践アプリケーション開発までそれでは。
オプション(メソッドのようなもの)
data
UIの状態・データ
Reactでいうstateみたいなものかな?変数のような概念かな?
このdata
を通して、html側にデータを送るようです。
名前から役割が想像しやすいですね。el
vueインスタンスをマウントする要素。
マウントがよく分かっていません。
el
でマウントすることで、該当htmlにデータを送受信したり、計算したり、加工したりできるようになる。メソッドによるマウントもでき、その場合は$mountを使うようです。
filters
データを文字列と整形する。
データを 計算 するのではなく、あくまでも整形する。
後述ののcomputed
と役割が被って見えます。methods
イベントが発生した時などの振る舞い。
onClick等の処理を書いているところですね。computed
データから派生して算出される値。
要は、受け取ったデータを 計算 しているものですね。
前述のfilters
と役割が被って見えます。テンプレート構文
{{}}
Mustache構文(二重中括弧)という名前らしいです。ディレクティブ
オプションと同じように、vue.jsで重要な概念の一つ。
ディレクティブにより、onClickで処理をメソッドに渡したり、繰り返しの構文を使えたり、formのデータを取得できるようです。v-bind
`v-bind: 属性名 = "データを展開した属性値"
buttonのdisableやstyleなどに、vueのデータやメソッドを挟み込めるようになりますね。省略記法として、
:
+ 属性名で記述できます。例<p v-bind:class="hoge"> ↓ <p :class="hoge">v-if/v-show
条件付きレンダリング。
名前だけやと分からないですね。
非表示・非表示を切り替える場合に使うものです。見た目上は同じような動きをしますが、v-ifはDOMの追加・削除を、v-showはdisplayプロパティの変更をするようです。
v-for
リストレンダリング。
jsのfor構文と同じく、html上でデータの繰り返し処理ができるようです。v-on
イベントハンドリング。
onClickやonChange属性にメソッドや処理を渡せるようです。省略記法として
@
があります。例<button v-on:click="hoge"> ↓ <button @click="hoge">v-model
フォーム入力バインディング。
双方向バインディングを実現できる。
Reactでは少し記述が冗長になるため、これは非常に便利!
- 投稿日:2019-08-29T22:55:14+09:00
vee-validate で「特定のフィールドに固有のバリデーションメッセージを設定する
はじめに
「特定のフィールドの regex バリデーションメッセージを変更したい」という要件が上がってきたんだけど、vee-validateではどう実現するのが正解がわからなかった。
やりたいこと
- regex のグローバルで設定しているバリデーションメッセージは変更したくない。
- 特定のフィールドの regex のバリデーションメッセージだけを変更したい。
- 他の検証ルールのメッセージはそのまま。
やったこと
lib/validatormessage.tsimport { Validator } from 'vee-validate'; export function getError( validator: Validator, field: string, ruleMsssageMap: { [rule: string]: string } ): string | null { const errors = validator.errors.items.filter((e) => e.field === field); if (errors.length > 0) { const error = errors[0]; let isExists = false; for (const rule in ruleMsssageMap) { if (error.rule === rule) { isExists = true; } } if (isExists) { return ruleMsssageMap[error.rule]; } else { return validator.errors.first(field); } } return null; }xxx.vue<template> <input type="text" name="myfield" v-model="myfieldValue" v-validate="{ required: true, regex: /[1-9]/ }" /> <div v-show="myfieldError"> {{ myfieldError }} </div> </template> <script lang="ts"> import { getError } from '@lib/validatormessage' ... computed: { myfieldError: { get: (): string | null => { return getError(this.$validator, 'myfield' { regex: 'cutome error message.' }) }, }, }, <script>まとめ
特定のフィールドで、他の検証ルールに影響をあたえず、特定の検証ルールにのみバリデーションメッセージを設定することに成功しました。
みんなはどのように実装しているんだろう…(゜_゜)
- 投稿日:2019-08-29T22:24:15+09:00
Vue.jsのローカル環境での使用方法
初めに
とあるインターン先でVue.jsを使うことになり、その勉強のメモのために記事を投稿してみました。
まず、Vue.jsとはJavascriptのフレームワークのことで、個人的な意見として、他のフレームワークに比べて内容が理解しやすいと感じました。
Vue.jsの勉強にはjsfiddleという無料で使えるサイトを使う場合もありますが、今回は自分のテキストエディタで使用する方法を解説していきます。方法
まずは、Vue.jsの公式サイトにアクセスし、ページ内でインストールと検索してください。その後、下のほうに移動すると、直接読み込み
あるため、開発バージョンをダウンロードしてください。
ここからは、エディタを使っていきます。先ほどダウンロードしたものと同じ場所にHTMLファイルを作成します。そして、そのHTMLファイルのbodyタグ内の1番初めに、
<script src = "vue.js"></script>
bodyタグ内の最後にをいれ、この中にVue.jsのコードを書いていきます。例として、
new Vue({
el: '#app',
data: {
url: 'https://jp.vuejs.org/',
toggle: true,
languages: ['Javascript' , 'Ruby' , 'Python']
}
})
と記述します。では、実際に動くか確かめてみましょう。先ほど記述した2つのコードの間に
```
<ul> <li v-for = "language in languages"> {{ language }} </li> </ul> <p> <input type = "text" v-model = "message"> </p>
```
と入れると、結果のように表示されるので、成功してといえます。
- 投稿日:2019-08-29T20:23:57+09:00
inline要素の改行のスペースが気になったのでvueのカスタムディレクティブで解決してみた
これはなに
inline要素内で改行するとスペースが入りこむので、見た目的に気になったりする
https://codepen.io/aokiken/pen/vYBLMyv
<div> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> // 出力結果 // 1 2 3 4 5 // 意図しないスペースを○で再現 // 1○2○3○4○5対応策
改行しなければスペースは入らない
<div> <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span> </div>閉じタグの>を改行ればスペースは入らない
<div> <span>1</span ><span>2</span ><span>3</span ><span>4</span ><span>5</span> </div>開始タグの<tag以下を改行ればスペースは入らない
<div> <span >1</span><span >2</span><span >3</span><span >4</span ><span >5</span> </div>コメントアウトを挟めばスペースは入らない
<div> <span>1</span><!-- --><span>2</span><!-- --><span>3</span><!-- --><span>4</span><!-- --><span>5</span> </div>jsで改行を取り除けばスペースはなくなる
<div id="js_remove_nl"> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <script> const removeWhiteSpaceDom = document.querySelector('#js_remove_nl') const removeWhiteSpaceHtml = removeWhiteSpaceDom.innerHTML.replace(/\s*<("[^"]*"|'[^']*'|[^'">])*>\s*/g, match => match.trim()) removeNlDom.innerHTML = removeWhiteSpaceHtml </script>cssでfont-sizeを0にすれば見た目上スペースはなくなる(コピペにスペースは入り込む)
<div class="remove_whitespace"> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .remove_whitespace { font-size: 0; } .remove_whitespace > span { font-size: initial; } </style>float: left(コピペにスペースは入り込む)
<div class='float_left'> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .float_left:after { content: ""; display: block; clear: both; } .float_left > span { float: left; } </style>display: flex(コピペに段落は入り込む)
<div class='flex'> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .flex { display: flex } </style>vueのカスタムディレクティブで解決してみる
https://www.npmjs.com/package/vue-remove-whitespace
<div v-remove-whitespace> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> // 出力結果 // 12345余談
英語圏だと、単語の間にスペースが入るのが基本だから、問題視されないのかなーという
- 投稿日:2019-08-29T20:23:57+09:00
inline要素の改行のスペースが気になったのでvueのカスタムディレクティブ作成して解決してみた
これはなに
inline要素内で改行するとスペースが入りこむので、見た目的に気になったりする
https://codepen.io/aokiken/pen/vYBLMyv
<div> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> // 出力結果 // 1 2 3 4 5 // 意図しないスペースを○で再現 // 1○2○3○4○5vueのカスタムディレクティブで解決してみる
https://www.npmjs.com/package/vue-remove-whitespace
<div v-remove-whitespace> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> // 出力結果 // 12345その他の対応策
改行しなければスペースは入らない
<div> <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span> </div>閉じタグの>を改行ればスペースは入らない
<div> <span>1</span ><span>2</span ><span>3</span ><span>4</span ><span>5</span> </div>開始タグの<tag以下を改行ればスペースは入らない
<div> <span >1</span><span >2</span><span >3</span><span >4</span ><span >5</span> </div>コメントアウトを挟めばスペースは入らない
<div> <span>1</span><!-- --><span>2</span><!-- --><span>3</span><!-- --><span>4</span><!-- --><span>5</span> </div>jsで改行を取り除けばスペースはなくなる(カスタムディレクティブでも同様のことやってる)
<div id="js_remove_nl"> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <script> const removeWhiteSpaceDom = document.querySelector('#js_remove_nl') removeNlDom.innerHTML = removeWhiteSpaceDom.innerHTML.replace(/\s*<("[^"]*"|'[^']*'|[^'">])*>\s*/g, match => match.trim()) </script>cssでfont-sizeを0にすれば見た目上スペースはなくなる(コピペにスペースは入り込む)
<div class="remove_whitespace"> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .remove_whitespace { font-size: 0; } .remove_whitespace > span { font-size: initial; } </style>float: left(コピペにスペースは入り込む)
<div class='float_left'> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .float_left:after { content: ""; display: block; clear: both; } .float_left > span { float: left; } </style>display: flex(コピペに段落は入り込む)
<div class='flex'> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .flex { display: flex } </style>余談
英語圏だと、単語の間にスペースが入るのが基本だから、問題視されないのかなーという
- 投稿日:2019-08-29T20:23:57+09:00
inline要素の改行のスペースが気になったので対策を調べた
これはなに
inline要素内で改行するとスペースが入りこむので、見た目的に気になったりする
https://codepen.io/aokiken/pen/vYBLMyv
例えば、以下のような、文章の途中のリンクなどに困る
<p> お問い合わせは <a href="#">こちらから</a> お願いします </p> // 出力結果 // お問い合わせは こちらから お願いしますサンプルはあくまで例だが、前後の文章やaタグにclassやattributeなど、内容によっては1行で表現しづらい
vueのカスタムディレクティブを作って解決してみる
https://www.npmjs.com/package/vue-remove-whitespace
<div v-remove-whitespace> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> // 出力結果 // 12345その他の対応策
改行しなければスペースは入らない
<div> <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span> </div>閉じタグの>を改行ればスペースは入らない
<div> <span>1</span ><span>2</span ><span>3</span ><span>4</span ><span>5</span> </div>開始タグの<tag以下を改行ればスペースは入らない
<div> <span >1</span><span >2</span><span >3</span><span >4</span ><span >5</span> </div>コメントアウトを挟めばスペースは入らない
<div> <span>1</span><!-- --><span>2</span><!-- --><span>3</span><!-- --><span>4</span><!-- --><span>5</span> </div>jsで改行を取り除けばスペースはなくなる(カスタムディレクティブでも同様のことやってる)
<div id="js_remove_nl"> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <script> const removeWhiteSpaceDom = document.querySelector('#js_remove_nl') removeNlDom.innerHTML = removeWhiteSpaceDom.innerHTML.replace(/\s*<("[^"]*"|'[^']*'|[^'">])*>\s*/g, match => match.trim()) </script>cssでfont-sizeを0にすれば見た目上スペースはなくなる(コピペにスペースは入り込む)
<div class="remove_whitespace"> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .remove_whitespace { font-size: 0; } .remove_whitespace > span { font-size: initial; } </style>float: left(コピペにスペースは入り込む)
<div class='float_left'> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .float_left:after { content: ""; display: block; clear: both; } .float_left > span { float: left; } </style>display: flex(コピペに段落は入り込む)
<div class='flex'> <span>1</span> <span>2</span> <span>3</span> <span>4</span> <span>5</span> </div> <style> .flex { display: flex } </style>余談
英語圏だと、単語の間にスペースが入るのが基本だから、問題視されないのかなーという
- 投稿日:2019-08-29T19:16:02+09:00
ionic + vueでqr-scannerを使いたい時のメモ(自分用)
https://qiita.com/reon777/items/82f6292248d76d1f3360
ここでvue.jsにcordovaをインストールする*ここはかなり手こずった。
*cordovaをインストールする場所に要注意
https://github.com/ionic-jp/capacitor-docs/blob/master/site/docs-md/cordova/using-cordova-plugins.md
*capacitorでcordovaのプラグインを使う時の方法
$ npm install @ionic-native/qr-scanner
$ npm install cordova-plugin-qrscanner
$ npx cap syncこの時エラー文大量に出てきたけど無視して行った。
https://ionicframework.com/docs/native/qr-scanner
これとは微妙に書き方が違うので注意
qrscan.vuehoge() { const qrScanner = new QRScanner(); //新しくインスタンスを生成 // qrScanner.変数名でいろんな機能を使えるようになった qrScanner.prepare().then((status) => { if (status.authorized) { console.log('hogehoge') qrScanner.show(); const scanSub = qrScanner.scan().subscribe((text: string) => { console.log(text); qrScanner.hide(); scanSub.unsubscribe(); }); } }).catch((e) => { console.log(e); }); },
- 投稿日:2019-08-29T19:14:16+09:00
【Vue.js】Vuejsをchromeブラウザでデバッグする方法
開発環境
⭐️Mac book pro (Mac OS Mojave)
⭐️ブラウザ Google Chromehttps://twitter.com/nonnonkapibara/status/1166711295384510465
⛱️Vue.js⛱️CodePen⛱️
— non (@nonnonkapibara) August 28, 2019
Vue.jsをCodePenで実装してみたよぉ。
CDN(インターネット経由)でできるので、めっちゃ便利♪♪https://t.co/z92om6dOAu pic.twitter.com/FrcWwWINq0
Vuejsをchromeブラウザでデバッグする方法
1.Chromeのアドオン「Vue.js Devtools」を入れる。
Vue.js Devtools
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd
2.インストールが終わったらVue.js Devtoolsのアイコンを右クリックして「拡張機能を管理」を開く
3.「Vue.js Devtools」ONにして、「ファイルのURLへのアクセス許可する」をONにする
main.jsの上部に
Vue.config.devtools = true;4.Vue.jsページをChromeで開くと、Vue.js Devtoolsアイコンが有効になる。緑色がつく。
完了
- 投稿日:2019-08-29T16:42:30+09:00
【Rails】rails webpacker:install に失敗する場合の対処法
概要
Rails 5.1 + Vue.js で開発を行う - part1 環境構築を参考に構築済みのrails環境にvue.jsを追加しようとしていた。
webpackerをインストールするため、$rails webpacker:install
を実行したらコケる現象に遭遇したのでその解消法を記載する。環境
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18]
- Rails 5.2.3
- yarn 1.17.3
rails webpacker:install した時次のエラーが出力される
Errno::ENOENT: No such file or directory @ rb_sysopen - /Users/hoge/projects/testapp/config/webpacker.yml
どうやらtestapp/config配下にwebpacker.ymlがないことが原因らしい。
webpacker.ymlを生成するために$ rails webpacker:install
してるのに....apple-no-MBP:testapp hoge$ rails webpacker:install /Users/hoge/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/twitter-4.8.1/lib/twitter/cursor.rb:51: warning: circular argument reference - collection Faraday::Builder is now Faraday::RackBuilder. rails aborted! Don't know how to build task 'webpacker:install ' (See the list of available tasks with `rails --tasks`) Did you mean? webpacker:install webpacker:install:vue webpacker:install:erb webpacker:install:elm webpacker:binstubs /Users/hoge/projects/testapp/bin/rails:9:in `<top (required)>' /Users/hoge/projects/testapp/bin/spring:15:in `<top (required)>' bin/rails:3:in `load' bin/rails:3:in `<main>' (See full trace by running task with --trace) apple-no-MBP:testapp hoge$ bundle exec rails webpacker:install /Users/hoge/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/twitter-4.8.1/lib/twitter/cursor.rb:51: warning: circular argument reference - collection Faraday::Builder is now Faraday::RackBuilder. /Users/hoge/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/twitter-4.8.1/lib/twitter/cursor.rb:51: warning: circular argument reference - collection Faraday::Builder is now Faraday::RackBuilder. RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment rails aborted! Webpacker configuration file not found /Users/hoge/projects/testapp/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /Users/hoge/projects/testapp/config/webpacker.yml /Users/hoge/projects/testapp/config/environment.rb:5:in `<top (required)>' /Users/hoge/projects/testapp/bin/rails:9:in `<top (required)>' /Users/hoge/projects/testapp/bin/spring:15:in `require' /Users/hoge/projects/testapp/bin/spring:15:in `<top (required)>' ./bin/rails:3:in `load' ./bin/rails:3:in `<main>' Caused by: Errno::ENOENT: No such file or directory @ rb_sysopen - /Users/hoge/projects/testapp/config/webpacker.yml /Users/hoge/projects/testapp/config/environment.rb:5:in `<top (required)>' /Users/hoge/projects/testapp/bin/rails:9:in `<top (required)>' /Users/hoge/projects/testapp/bin/spring:15:in `require' /Users/hoge/projects/testapp/bin/spring:15:in `<top (required)>' ./bin/rails:3:in `load' ./bin/rails:3:in `<main>' Tasks: TOP => app:template => environment (See full trace by running task with --trace) apple-no-MBP:testapp hoge$ apple-no-MBP:testapp hoge$ apple-no-MBP:testapp hoge$ bundle exec rails webpacker:install /Users/hoge/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/twitter-4.8.1/lib/twitter/cursor.rb:51: warning: circular argument reference - collection Faraday::Builder is now Faraday::RackBuilder. /Users/hoge/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/twitter-4.8.1/lib/twitter/cursor.rb:51: warning: circular argument reference - collection Faraday::Builder is now Faraday::RackBuilder. RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment rails aborted! Webpacker configuration file not found /Users/hoge/projects/testapp/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /Users/hoge/projects/testapp/config/webpacker.yml /Users/hoge/projects/testapp/config/environment.rb:5:in `<top (required)>' /Users/hoge/projects/testapp/bin/rails:9:in `<top (required)>' /Users/hoge/projects/testapp/bin/spring:15:in `require' /Users/hoge/projects/testapp/bin/spring:15:in `<top (required)>' ./bin/rails:3:in `load' ./bin/rails:3:in `<main>' Caused by:Errno::ENOENT: No such file or directory @ rb_sysopen - /Users/hoge/projects/testapp/config/webpacker.yml /Users/hoge/projects/testapp/config/environment.rb:5:in `<top (required)>' /Users/hoge/projects/testapp/bin/rails:9:in `<top (required)>' /Users/hoge/projects/testapp/bin/spring:15:in `require' /Users/hoge/projects/testapp/bin/spring:15:in `<top (required)>' ./bin/rails:3:in `load' ./bin/rails:3:in `<main>' Tasks: TOP => app:template => environment (See full trace by running task with --trace)エラー遭遇までに実行したことなど
rails環境にvue.jsを導入する時はたぶん以下の手順が一般的かも
- Gemfileに
gem 'webpacker', github: 'rails/webpacker'
を書き込んで$bundle install
→OK- yarnのインストール。
$ brew install yarn
or$brew upgrade yarn
→OK- webpackerのインストール。
$ rails webpacker:install
→エラー発生対処法
$ rails webpacker:install
する前にwebpacker.ymlをつくった。めちゃくちゃ野蛮な解決法。
一応同様のissueはすでに上がっており、そこに載ってた対処法。
https://github.com/rails/webpacker/issues/940以下のソースコードをコピペ→config配下にwebpacker.ymlをつくってその中にペースト。
https://raw.githubusercontent.com/rails/webpacker/master/lib/install/config/webpacker.ymlおしまい。たぶんyarnのバージョンが原因な気はしている。
- 投稿日:2019-08-29T15:26:23+09:00
Docker+Vue.js+Vuetify環境構築
この記事について
VSCodeのRemoteを使って、Dockerコンテナー内に、Vue.js+Vuetify環境を構築するためのメモです。
対象
- VSCodeはある程度使い慣れている
- VSCodeのRemote container拡張機能は使った事がある
dockerfile作成
EXPOSE 9000でポート指定をする事を忘れないように。
最悪コピペでもOKdockerfileFROM node:lts WORKDIR /app RUN npm install -g npm && \ npm install -g @vue/cli EXPOSE 9000 CMD ["/bin/sh"]dockerビルド
VSCode Remote Containerを使用して、ビルドを行う。
Vue-Cliインストール
shell$ npm install -g @vue/cliVueプロジェクト作成
コマンドを叩いた後に、途中で選択肢が出るので、
default
とUse NPM
を選択shell$ vue create sandbox > default (babel, eslint) > Use NPMVSCode RemoteでPORT設定
Forewd Port from Containerを選択し、
8080
を入力Vueの動作確認
shell$ cd sandbox $ npm run serveコマンドを叩いた後に、
localhost
にアクセス
http://localhost:8080/studio動作確認できたら、
ctrl+c
で一旦終了。Vuetify インストール
コマンドを叩いた後に、選択肢があるので
Default (recommended)
を選択shell$ vue add vuetify > Default (recommended)
- 投稿日:2019-08-29T15:26:23+09:00
GitHub PagesにDocker+Vue.js+Vuetifyでページを公開
この記事について
VSCodeのRemoteを使って、Dockerコンテナー内に、Vue.js+Vuetify環境を構築するためのメモです。
対象
- VSCodeはある程度使い慣れている
- VSCodeのRemote container拡張機能は使った事がある
dockerfile作成
EXPOSE 8080でポート指定をする事を忘れないように。
最悪コピペでもOKdockerfileFROM node:lts WORKDIR /app RUN npm install -g npm && \ npm install -g @vue/cli EXPOSE 8080 CMD ["/bin/sh"]dockerビルド
VSCode Remote Containerを使用して、ビルドを行う。
Vue-Cliインストール
shell$ npm install -g @vue/cliVueプロジェクト作成
カレントディレクトリにvueプロジェクトを作成する
コマンドを叩いた後に、途中で選択肢が出るので、
yes
>default
>Use NPM
を選択shell$ vue create . > Y > default (babel, eslint) > Use NPMVSCode RemoteでPORT設定
Forewd Port from Containerを選択し、
8080
を入力Vueの動作確認
shell$ npm run serve
コマンドを叩いた後に、
localhost
にアクセス
http://localhost:8080/studio動作確認できたら、
ctrl+c
で一旦終了。Vuetify インストール
コマンドを叩いた後に、選択肢があるので
Default (recommended)
を選択shell$ vue add vuetify > Default (recommended)ビルドディレクトリ変更
/node_modules/@vue/cli-service/lib/options.js
options.js<省略> exports.defaults = () => ({ // project deployment base publicPath: '', // for compatibility concern. TODO: remove in v4. baseUrl: '', // where to output built files // outputDir: 'dist', outputDir: 'docs', assetsPublicPath: '', // where to put static assets (js/css/img/font/...) assetsDir: '', // filename for index.html (relative to outputDir) indexPath: 'index.html',ビルド
docsディレクトリにビルドされたファイルが格納されるので、そのままGitHub Pagesにデプロイできます。
shell$ npm run build
Vue routerを入れる
shell$ vue add router
- 投稿日:2019-08-29T13:08:42+09:00
30分でわかるVue.js入門
目的
フロントエンドのJSを知らないので、どれでもいいので理解したい。
フロントエンドで主流は廃れたJQueryを除くと3つある。
1. Angular.js
2. React.js
3. Vue.js
このなかで、Github上で一番人気があるのがVue.jsである。
なので、Vue.jsのザックリ理解するために入門編としてまとめてみた。1.Vue.jsとは
JavaScriptフレームワークの1つで、MVCモデルのView層を扱います。
読み方:ビュードットジェイエス
特徴:学習コストが低い※スペルを間違えやすいので、声に出すと間違えない。
○:ブイユーイー
✗:ブイイーユー対象ブラウザ:ECMAScript5(エクマスクリプト)をサポートするブラウザ。
簡単に言うと、最近のJavaScript標準をサポートするブラウザ。→Chrome,IE9以降
2.ツール
Vue DevtoolsというChromeの拡張機能が公開されている。
https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=ja&
検索ワード:vue chrome プラグインNuxt.jsという便利なフレームワークも提供されており、そちらを使うようになってからは
もっぱらVSCodeを利用している。VSCode
https://azure.microsoft.com/ja-jp/products/visual-studio-code/VSCode日本語化
https://qiita.com/ohno888/items/b9e955a2ab1ad0e097673.セットアップ
Vueはライブラリなので、downloadして読み込ませるか、CDNを利用する。
https://jp.vuejs.org/v2/guide/installation.html
以下、CDNが使えるのでそちらを利用して開発できる。
※CDNとはコンテンツデリバリーネットワークの略で、大容量のデジタルコンテンツをインターネット上で大量配信するためのネットワークのこと。4.さっそくHello World
hello.html<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue.js</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <!--Vueデータを出力する--> <div id="app">{{ msg }}</div> <script> // id=appの要素にVueを適用する const app = new Vue({ el:'#app', data:{ msg:'Hello World!' } }) </script> </body> </html>解説
(1){{プロパティ名}}でデータ出力する。
(2)elプロパティはオブジェクトを割り当てる。キー名:値の形式で指定する。作法だけ覚えれば簡単。チートシートなどを用意すれば誰でも書ける。
5.次はイベントハンドリング(ボタンアクション)
event.html<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue.js</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <!--Vueデータを出力する--> <div id="app"> <button v-on:click="changeMsg">change</button> <p>{{ msg }}</p> </div> <script> // id=appの要素にVueを適用する const app = new Vue({ el:'#app', data:{ msg:'hoge' }, methods:{ changeMsg:function(){ this.msg = 'fuga' } } }) </script> </body> </html>解説
「v-on:DOMイベント」でイベントハンドリングが実装できる。
methodsプロパティに呼び出されるメソッドを記述する。6.コンポーネント
component.html<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue.js</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <!--Vueデータを出力する--> <div id="app"> <my-comp></my-comp> </div> <script> Vue.component('my-comp',{ template:'<h1>hogehoge</h1>' }) var app = new Vue({ el:'#app', }) </script> </body> </html>解説
コンポーネントは「Vue.component()」で定義します。
templateプロパティにコンポーネントに含める要素を指定します。7.ディレクティブ
Vue.jsではHTMLタグに「v-**」の属性を指定することができ、これを「ディレクティブ」と呼びます。
ディレクティブを使いこなすことが、Vue.jsを使いこなす第一歩と言えます。代表的なディレクティブ
v-text テキストをレンダリングする
v-html HTMLをレンダリングする。タグも変換しないで出力します。
でタグもHTMLで出力できます。rawHTMLが値v-show 条件に応じたレンダリング制御を行う
CSSのdisplayプロパティで表示を制御v-if,v-else,v-else-if 条件分岐を行う
要素自体の有無を制御v-for 繰り返しを行う
v-on イベントハンドリングを実装する
@で記述を省略することができます。v-bind HTML属性を割り当てる
:で記述を省略することができます。v-model 入力フォームへモデルを割り当てる
input,select,textareaに対してVueオブジェクトのデータとフォーム部品の値を関連付けます。v-pre テキストをそのまま出力する
v-once 一度だけレンダリングする
レンダリングを1度だけ行い、それ以降は変数が変動しても、表示に反映させなくします。8.最後は実践例(リアルタイム入力チェック)
validation.html<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue.js</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <style> #app .error{ color: red; } </style> </head> <body> <!--Vueデータを出力する--> <div id="app"> <input type="text" v-model="msg"> <div class="error" v-if="error.require">必須項目です</div> <div class="error" v-if="error.tooShort">短すぎます</div> <div class="error" v-if="error.tooLong">長すぎます</div> </div> <script> const app = new Vue({ el:'#app', watch:{ msg:function(newVal, oldVal){ this.error.require = (newVal.length < 1)?true:false; this.error.tooShort = (newVal.length < 3 && newVal.length > 0)?true:false; this.error.tooLong = (newVal.length > 5)?true:false; } }, data:{ msg:'hoge!', error: { require: false, tooShort: false, tooLong: false } } }) </script> </body> </html>解説と注意点
watchは、入力値を監視するためのオプション。
Vueのメソッドやプロパティはカンマでつなぐ必要あり。忘れやすいので注意。上でいうとdataの前のカンマ
app .errorの指定で、appの後ろに空白が必要
以上でVue.jsの入門編は終わり。
他にもVue RouterやVuexなど色々あるが、
まずは上記を押さえれば入門者としては良いと考えています。今後の記載予定
入門編:当記事
初級者編:Vue CLI、Vue Router、Vuexなど
中級者編:Nuxt.jsなどを利用し他システムとの連携
- 投稿日:2019-08-29T11:34:06+09:00
【Vuetify on Nuxt.js】実際に本番運用したコンポーネントとそのカスタマイズ
概要
本スライドはVuetify Meetup #1での発表資料です。面白そうと思った方はぜひ次回以降参加してください!LTも募集中です。
自己紹介
業務内容
Twitter @Meijin_garden
名人って呼ばれてます。株式会社NoSchoolのCTO。
中高生のための勉強質問サイトを作ってます。
自分しかフルタイムのエンジニアがいないのでAWSもFirebaseもLaravelもNuxt.jsもデザインも採用も機械学習もやってます。
経歴
奈良高専情報工学科
↓
株式会社LIFULL
↓
株式会社NoSchool
Vuetify on Nuxt.jsを採用した理由
背景
2017年からNoSchoolのサイト自体はあるが、社長がWordPress on SakuraServerで起業したのでエンジニアから見たら酷いものだった。
シードの資金調達を終えて僕がジョインした2019年3月から5月にかけて、フルリプレイスを行うこととなった。
リプレイス後の技術構成
インフラ: AWS(CloudFront, ALB, EC2, S3...)
サーバーサイド: Laravel
フロントエンド: Nuxt.js, jQuery※2ヶ月じゃフロントまで移行やりきることができず、現在もページ単位でNuxtに移行中
Nuxt.jsの採用理由
- 僕自身がVue.jsの経験が1年強あった(前職の新規事業で1人でフルスクラッチした)
- jQueryと比較して開発速度が段違い
- ReactとVueだとあまり違いも採用力が衰えるということもなさそうなのでCTOの僕が経験があって開発速度がとにかく速いものを選べばいいやという考え
Vuetifyの採用理由
- デザイナー不在でそこそこの品質で開発をするためにUIフレームワークは必須
- Bulma、Bootstrap Vueなども見たが、Class属性ではなくコンポーネント自体を用意してくれている方が使い勝手がいいと思った
- ちなみにElementは前職で使っていたけどレスポンシブや細かいところでイライラした
実際にVuetifyで頑張ったページたち(2019/8時点)
家庭教師一覧
家庭教師詳細
質問作成
Vuetifyでまずこれだけ覚えておけば的なコンポーネントリスト
- ページ(
v-app
,v-content
等)- レイアウト(
v-layout
,v-flex
)- 余白(
.py-2
,.mx-4
等)- 装飾系(
v-card
,v-chip
,v-icon
)- 画像系(
v-img
,v-avatar
)- フォーム(
v-btn
,v-select
,v-text-field
等)- あとはドキュメントを読み込む。カスタムSlotも便利。
Vuetifyの便利コンポーネントをいくつか紹介
ページ構成(default.vue)
<template lang="pug"> v-app my-header v-content(app) my-breadcrumbs(:items="breadcrumbs") v-container(app fluid) nuxt my-footer </template>※ちょっと改変はしてます
v-app
やv-content
などは公式ドキュメントの通り。
パンくず(Breadcrumbs.vue)
パンくずはv-breadcrumbsがベースで、カスタマイズのために
v-slot:item
を利用。<template lang="pug"> v-breadcrumbs(:items="items").px-2.py-0.grey.lighten-3 template(v-slot:item="props") v-breadcrumbs-item( :to="props.item.to" :disabled="props.item.disabled" v-if="props.item.to !== '/'" ) span.grey--text {{ props.item.text }} span(v-else) a(href="/").pa-0 v-icon.body-1.primary--text mdi-{{ props.item.icon }} template(v-slot:divider) span > </template>
ページネーション
<template lang="pug"> v-pagination( v-model="pageModel" @input="onPaginationClicked" @next="onPaginationClicked" @previous="onPaginationClicked" :length="last_page" :total-visible="7" style="overflow-x: scroll;" ).my-4 </template>scriptを抜粋するとこんな感じ。
<script> export default { ... methods: { onPaginationClicked(event) { this.$emit("query-updated", { page: this.pageModel }); } } ... }; </script>要は、ページネーションのページ番号が変わったときに呼び出し元コンポーネントで再度API叩くなりする必要があるので、親にemitする設計にしている。
ページネーションの注意
total-visibleが偶数だと、中央あたりのページ番号で表示が変になるので注意。
例えば6にしたとき、全ページ数が10などのときに5ページ目付近で表示がおかしくなり、隣り合ったページが表示されない。
これは...も含めたvisibleのcountだから、偶数だと...の数が合わなくて隣り合ったページが出ない。
(気になるなら直せやOSSだろという話ですよねすみません)
Vuetifyをベースにカスタマイズしているコンポーネント
見出し系
Vuetifyの見出しはフォントサイズが大胆なのと、サイト全体で統一感を出したいので共通コンポーネント化。
plugin/globalComponent.jsimport Vue from 'vue' import Body from "@/components/layouts/Body"; import PageTitle from "@/components/parts/heading/pageTitle"; import SubTitle from "@/components/parts/heading/subTitle"; import SubTitle2 from "@/components/parts/heading/subTitle2"; Vue.component('sec-main', Body) Vue.component('page-title', PageTitle) Vue.component('subtitle', SubTitle) Vue.component('subtitle2', SubTitle2)悩ましいのは、マージンまでコンポーネントに入れるかどうか。入れるとしたらどれくらい大きいマージンを入れるか(デザインの話になってくるけど)。
ボタン
サイトを作っていく中で、
outlined
なv-btn
をよく使うので共通化。<template lang="pug"> v-btn(outlined large :color="color" :to="to" @click="clicked" :block="block").py-2.mt-2 v-icon(v-if="icon" :class="iconColor + '--text'").title.mr-2 mdi-{{ icon }} .subtitle-1 slot </template> 以下略
必須ラベル
最近作ったatoms的なのでかなり気に入ってる。
<template lang="pug"> v-chip(small label color="accent").px-2.font-weight-bold 必須 </template>
駆け足でしたがLTなのでこれくらいにします
最後に
NoSchoolではフロントエンドが得意で、Laravel等のサーバーサイドもゴリゴリやっていきたいWebエンジニアを募集中です!(iOSエンジニアも!)
回答最適化のために機械学習も取り入れていたり、勉強意欲の強い人が自由に暴れられると思いますので是非お声がけください〜。
- 投稿日:2019-08-29T10:09:04+09:00
Vuetifyの気になるコンポーネントまとめ
Vuetifyのコンポーネントで良さそうなのを個人的にまとめてみた。
勉強のついでに気になるコンポーネントをまとめてみた。
Overlays
背景マスクを簡単に作ってくれる。absolute指定でブロックに限定するのが簡単にできる。ダイアログやライトボックスなどを自前で作るときに便利
##App Bars
ヘッダーくらい自分で作れと言われそうだが、めんどくさいのもまた事実。最近流行りのヘッダーラインより少し下にメニューをつける手法ができるが、応用ができなかったら結局自分で作りそう。
Collapseはなんか見慣れない不思議な動き。Color pickers
Data iterators
例として成分表示表が使われてるけど、比較しない単体での表示が必要な場合は使いたい。filterやsearchが強力なのが嬉しい。
Tabs
Tabs
縦型にも対応しているし、スマホだとフリック操作でスライドもする。Timelines
略歴とかバージョンアップ履歴とかに便利なコンポーネント。
avatarとかなかなか面白いTreeview
適当にjson投げると表示を綺麗にしてくれそうなあれ。セレクトは下位の要素も同時に選択できる。
Steppers
長い操作が必要な場合に画面分割&経過を視覚的に見せる。
カートとかで使われてるが、入力項目が多い場合に汎用的に使用できる。
縦型にすることもできるのでなかなか面白い。まとめ
まだまだ他にも色々面白いものがありそう。使えそうだったら楽して組み込みたいなぁ
- 投稿日:2019-08-29T06:49:15+09:00
Nuxt.js + GraphQL + Ruby on Railsで作ったアプリにJWT認証を追加する方法
本記事ではフロントエンドに Nuxt.js(Vue.js)、バックエンドに Ruby on Rails 、APIに GraphQL を採用したアプリケーションに、JWTトークンによる認証 を追加する方法についてまとめます。
題材
サンプルとして以下チュートリアルで作成したToDoリストを使用します。
Nuxt.js + GraphQL + Ruby on Railsで作るToDoアプリチュートリアル(前編)
Nuxt.js + GraphQL + Ruby on Railsで作るToDoアプリチュートリアル(後編)JWTでの認証フロー
今回実装するJWTでの認証フローを図にまとめました。
トークンの発行・保存・付与・検証がめんどくさそうに見えるかもしれませんが、フロントエンド側はAuth Moduleが、バックエンド側はknockがトークンをいい感じに処理してくれるので、安心してください。
実装(バックエンド)
ユーザモデルを定義する
認証単位となるモデル(User)を生成します。
$ bundle exec rails g model user email:string password_digest:string $ bundle exec rails db:migrateUserはパスワードをハッシュ化して管理するので、モデルに
has_secure_password
を宣言します。app/models/user.rbclass User < ApplicationRecord has_secure_password endまた、Gemfileの
bcrypt
のコメントを外します。Gemfile# ・・・中略・・・ # Use Active Model has_secure_password gem 'bcrypt', '~> 3.1.7 # ・・・中略・・・テスト用のUserを
seed.rb
に追記します。db/seeds.rb# ・・・中略・・・ User.create( email: 'test@example.com', password: 'xxxxxxxx', password_confirmation: 'xxxxxxxx' )$ bundle exec rails db:seedknockをインストールする
Gemfileにknockを追加し、インストールします。
Gemfilegem 'rack-cors' gem 'graphql' gem 'knock' # ★追加$ bundle installRails6だとknockのautoloadに失敗するのでinitializerで明示的にrequireします。
config/initializers/eager_load_knock.rbrequire 'knock/version' require 'knock/authenticable'ジェネレータを実行します。
$ rails generate knock:install
ログイン/ログアウトのエンドポイントを準備
ジェネレータでControllerを生成します。
$ rails generate knock:token_controller user
各Controllerにて認証処理を行えるようにするため、
ApplicationController
にてmoduleをincludeします。app/controllers/application_controller.rbclass ApplicationController < ActionController::API include Knock::Authenticable end
GraphqlController
のbefore_actionとして認証処理を追加します。app/controllers/graphql_controller.rbclass GraphqlController < ApplicationController before_action :authenticate_user # ・・・中略・・・ end今回、セッションは使わないのとCORS設定済みであることを考慮して、CSRF対策を解除します。
config/application.rb# ・・・中略・・・ module RailsNuxtGrapshqlTodoapp class Application < Rails::Application config.load_defaults 6.0 config.api_only = true config.action_controller.default_protect_from_forgery = false end end動作確認(バックエンド)
サーバ起動してInsomniaを使ってリクエストを送信してみます。
$ bundle exec rails s未認証の状態でGraphQL Queryを送信しても、
401
が返ってきます。
/user_token
へリクエストすると、JWTトークンが返ってきます。Bearerの設定でTOKEN欄に上記JWTトークンを記載します。
この状態で再度GraphQL Queryを送信すると、
200
が返ってきました。
JWT認証が機能していますね。実装(フロントエンド)
Auth Moduleをインストールする
npmでインストールします。
Auth Moduleはstore/index.js
が存在していないとエラーを出すので、空のファイルを作成しておきます。$ npm install @nuxtjs/auth @nuxtjs/axios $ touch store/index.js
nuxt.config.js
のmodules
,axios
,auth
,apollo
を追記します。// ・・・中略・・・ modules: [ '@nuxtjs/vuetify', '@nuxtjs/pwa', '@nuxtjs/eslint-module', '@nuxtjs/apollo', '@nuxtjs/axios', '@nuxtjs/auth' ], axios: { baseURL: 'http://localhost:3000/' }, auth: { strategies: { local: { endpoints: { login: { url: 'user_token', method: 'post', propertyName: 'jwt' }, user: false, logout: false } } } }, // ・・・中略・・・ apollo: { clientConfigs: { default: { httpEndpoint: 'http://localhost:3000/graphql', getAuth: () => '' } } } // ・・・中略・・・ログイン画面を準備
/login
に相当する画面およびログイン処理を実装します。pages/login.vue<template> <v-container> <v-row> <v-col cols="6" offset="3"> <v-card> <v-card-title>Login</v-card-title> <v-card-text> <v-form> <v-container> <v-row> <v-col cols="6"> <v-text-field v-model="email" label="Email" required /> </v-col> </v-row> <v-row> <v-col cols="6"> <v-text-field v-model="password" type="password" label="Password" required /> </v-col> </v-row> <v-row> <v-col> <v-btn @click="login()"> Login </v-btn> </v-col> </v-row> </v-container> </v-form> </v-card-text> </v-card> </v-col> </v-row> </v-container> </template> <script> export default { middleware({ store, redirect }) { window.console.log(store.state.auth.loggedIn) if (store.state.auth.loggedIn) { return redirect('/') } }, data() { return { email: '', password: '' } }, methods: { async login() { try { await this.$auth.loginWith('local', { data: { auth: { email: this.email, password: this.password } } }) await this.$apolloHelpers.onLogin(this.$auth.getToken('local').match(/^Bearer[ ]+([^ ]+)[ ]*$/i)[1]) this.$router.push('/') } catch (e) { window.console.log(e) } } } } </script>無名middlewareを用いることで、既にlogin済みの状態でこのページを開くと、'/' でリダイレクトするようにしています。
methodsの
login()
がLOGINボタンを押したときの処理です。
Auth Moduleでログインをした後で、Apollo ModuleへJWTトークンをセットしています。ログアウトボタンを追加
ログイン中の場合のみ、メニューバーにログアウトボタンを表示します。
layouts/default.vue<template> <v-app> <v-app-bar app> <v-toolbar-title v-text="title" /> <div class="flex-grow-1" /> <span v-if="loggedIn" @click="logout()">Logout</span> </v-app-bar> <v-content> <nuxt /> </v-content> <v-footer center> <v-layout justify-center> <span>© 2019 Yuhei Okazaki. All Rights Reserved.</span> </v-layout> </v-footer> </v-app> </template> <script> export default { data() { return { title: 'Tasks' } }, computed: { loggedIn() { return this.$auth.loggedIn } }, methods: { async logout() { try { await this.$auth.logout() await this.$apolloHelpers.onLogout() this.$router.push('/login') } catch (e) { window.console.log(e) } } } } </script>methodsの
logout()
がLOGOUTを押したときの処理です。
Auth Moduleでログアウトをした後で、Apollo Moduleもログアウトしています。未認証時のリダイレクトを追加
このままだと、ログインしていない状態でもタスク一覧画面を開けてしまうので、ログインしていないときには
/login
へ飛ばすようmiddlewareを設定します。pages/index.vue// 中略 export default { middleware: 'auth' // 中略 }動作確認(全体)
冒頭の画像のように、ログインしたときのみタスク一覧が表示されます。
まとめ
本記事ではバックエンドにRuby on Rails、フロントエンドにNuxt.js、APIにGraphQLを採用したアプリケーションにJWT認証を追加しました。
新規登録画面やタスクとユーザの紐付け等、未実装の処理は多数あるものの、認証というアプリケーションを実装するときの最初の壁は越えられたかと思います。knockやAuth Module、Apollo Moduleを用いたことで、トークン操作を意識せず簡単に認証追加できたので、ぜひお試しください。