どうも、フリーランスエンジニアのウェブ系ウシジマくんです。
今Webエンジニア界隈のTwitterで話題になっている初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービスってご存知ですか?
たった500円でフロントエンドのフレームワークの一つであるvue.jsについて、実際にマークダウンのメモアプリを作りながら学ぶことができるという。
Vue.jsの入門書を書店で買うと2000円以上はするのに、それに負けじ劣らずの濃い内容なのも魅力です。
著者ワタナベさん曰く、
とのことなので、熱い想いに答えるべく実際に購入してアプリを作成!
作成したアプリ
Githubリポジトリ
今回の記事では作成する中で、Vue.jsについて自分がわからなかった点・ポイントを自分なりにまとめてみました。
また、書籍では紹介していませんが、作成する上で環境構築はvagrantで行っています。
初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービスの内容に沿ってまとめているので、照らし合わせながら見ていただくと、より理解しやすいと思います!
今回の記事の対象者
- Railsに携わるエンジニアとしてフロントエンドの知識を学び人
- Vue.jsについて基礎を学びたい人
- SPAを実際に作ってみたい人
- vue.jsをvagrantで動かしたい人
vagrantでvue.jsの環境を構築する方法
Vagrantfileに以下の情報を記述(ゲストOS側)します。ポート番号とホスト名を指定することで、ローカルのブラウザで表示させることができます。
config.vm.network "forwarded_port", guest: 8881, host: 8881 # webpack-dev-server
config.vm.network "forwarded_port", guest: 9005, host:9005 # for firebase login
vagrantfileを設定したら、アプリのルート配下にあるwebpack.config.jsの78~85行目あたりに以下の情報を記述(ホストOS側)しましょう。
78 devServer: {
79 host: '0.0.0.0',
80 port: 8881,
81 disableHostCheck: true,
82 historyApiFallback: true,
83 noInfo: true,
84 overlay: true
85 },
注意点
上記の設定を行うことでホスト名とポート番号をそれぞれ指定することになりますが、firebaseの認証済みドメインでは、localhostにポート番号を指定できないようです。
firebase.auth().onAuthStateChanged
そのため、上記のようなfirebase特有のメソッドを記述したまま、
npm run dev
でアプリケーションサーバーを立ち上げると編集画面に遷移しなくなるので、該当箇所をコメントアウトする必要があるので注意してください。
参考サイト
firebaseを使ったGoogleログインを実装する際のデータの流れ
googleログイン機能を実装する際に、出てきたthisメソッドについてこんがらがってしまったため、知識を整理するべくワタナベさんに質問してみました。
こんにちは!
初歩的な質問で恐縮ですが、お手すきの際にご回答いただけたら嬉しいです!
モモンガ本の28ページで使われているcreateメソッド内のthisって、これはuserのことを指しているのでしょうか?
created: function() {
firebase.auth().onAuthStateChanged(user => {
console.log(user);
if(user) {
this.isLogin = true;
} else {
http://this.is _Login = false;
};
});
},
この時のthisはapp.vueのインスタンス自体を示してます!
app.vueのdataで定義きた変数(isLogin)にデータを格納してる感じですね。
>上のthisはapp.vueのコンポーネントインスタンス自体で
>ルートインスタンスはmain.jsでnewした際のインスタンスになりますね。
>app.vueは今回のアプリの「rootコンポーネント」と言えるのでちょっとややこしいですね笑
ありがとうございます!
ちなみに、インスタンスについて以下のサイトを参考にしたのですが、app.vueのインスタンスって、ここでいうルートvueインスタンスとは別物ですか?
そうですね、別物です!
上のthisはapp.vueのコンポーネントインスタンス自体で
ルートインスタンスはmain.jsでnewした際のインスタンスになりますね。
なるほど、ちょっとこんがらがっていました(笑)
ということは、データの流れとしては、
1.ログインボタンが押されることでapp.vueでコンポーネントのインスタンスが作成される
2.created関数が発火
3.firebase.auth(),onAuthStateChagedでログイン情報をチェック
4.ログインされていたら、”user=>”の部分でuserという変数にユーザー情報を格納(アロー関数?)
5.ifの引数にuser変数を指定して、ユーザー情報の有無によってapp.vueインスタンス(this)をisLoginにture/falseとして格納
このような認識であってますか?
あっています!
インスタンスの概念はvue.jsだけでなくオブジェクト指向のプログラミング言語であれば必ず出てくるものです。
???となってしまった方は、以下のサイトで概要を掴んでみてください。
ディレクティブとは
v-ifやv-forなどの”v-“から始まる特殊な属性のことをディレクティブと呼びます。
vue.jsでのアプリケーションサーバー立ち上げ方法
npm run dev
railsでいうところの、 rails serverに相当します。
このコマンドを実行することで、アプリケーションサーバーを呼び出しています。
Mustache構文について
<h1>{{ msg }}</h1>
{{…}}の記号は、Mustache(マスタッシュ)構文と呼ばれるものでtemplate内でデータオブジェクトにアクセスするために使います。
script内で定義した値をプロパティとして表示するのが主だけど、Javascriptの式をそのまま展開することも可能。
ちなみに、Mustache構文とは口ヒゲのこと。”{“という記号を横向きにすると口ひげに見えることから名付けられているらしいです。
コンポーネントの読み込みについて
import Home from ‘./components/Hoge.vue’
export default {
(省略)
components: {
'Hoge': Hoge,
},
}
App.vueファイル内で別のコンポーネントを読み込む時には、scssなどと同じようにimportし、それをcomponets内で定義すればOK。
v-ifについて
条件付きのレンダリングと呼ばれるもの。javascriptでいうif文に相当し、true/falseとして評価できる式を指定します。
データオブジェクト(data..returnの部分)で定義した変数を渡すことでコンポーネントの表示/非表示を決めています。
<div class="" v-if = "isLogin">
<Editor></Editor>
</div>
<div class="" v-else>
<Home></Home>
</div>
ちなみに、上と下はどちらも挙動は同じですが、上はもう一つの条件レンダリングであるv-elseディレクティブを使っているため、順序が違います。
<div v-if = "!isLogin">
<Home></Home>
</div>
<div v-if = “isLogin">
<Editor></Editor>
</div>
v-onディレクティブについて
v-on: ‘イベント名':
イベントの紐付けに使われるディレクティブ。使用頻度が高いので、省略記法として、次の書き方が用意されています。
@click=“イベント名”
そのため、次のコードは全く同じ挙動になります。
# 省略記法
<template>
<div id="home">
<h1>{{msg}}</h1>
<button @click = "googleLogin">Googleアカウントでログイン</button>
</div>
</template>
# 通常の記法
<template>
<div id="home">
<h1>{{msg}}</h1>
<button v-on:click = "googleLogin">Googleアカウントでログイン</button>
</div>
</template>
どっちの記法でも問題ないが、可読性を高めるためにも記法は揃える方がベターでしょう。
メソッドの定義方法
コンポーネントで呼び出す関数を設定するには、method: {}を使って、その中にメソッド名.function() {}とすればいいです。
methods: {
hoge.functionn: {
}
}
v-bindディレクティブについて
template内で使用するタグの中で、属性値にjavascriptから渡された値を埋め込むのに使うのがv-bindディレクティブ。
v-onディレクティブと同じように使用頻度が高いので、省略記法が用意されています。
以下二つの書き方は全く同じです。
# 省略記法
<Editor v-if = "isLogin" :user="userData"></Editor>
# 通常の記法
<Editor v-if = "isLogin” v-bind:user="userData"></Editor>
プロパティについて
props['プロパティ名']
コンポーネントにパラメータを渡すことができます。これによって親コンポーネントからデータを受け継ぐことができるので、動的にデータのやりとりができるのが特徴。
動的とは、状態や構成が状況に応じて変化したり、状況に合わせて選択できたりする柔軟性を持っていること。対義語は「静的」「スタティック」(static)。
引用:IT用語辞典http://e-words.jp/w/%E5%8B%95%E7%9A%84.html
文字列として定義されるので、そのままの状態だと数値を渡しても中身はstrignsのままになってしまいます。数値を渡したい場合はv-bindディレクティブを使う必要があることに注意。
また、[]の中に記述するプロパティ名は全て小文字でハイフンで区切る点にも注意しましょう。
◯:props['user-status']
×:props[userstatus']
×:props[UserStatus']
参考
v-modelについて
v-modelを使うことで双方向データバインディング機能を実装することができます。双方向というのは、テンプレートで入力された値(テキスト入力部分)とデータオブジェクト(dataで定義されたメソッド)を紐付けることで互いの値が即座に更新されるというものです。
書籍内ではこのv-modelにmarkdownを指定することによって、データオブジェクトにテキストエリアで入力された値を格納しています。(データオブジェクト内でmarkdownを空文字にしているのはそのため)
markdownに格納された値をpreviewメソッドにthisで渡すことでプレビュー機能を実装していることになります。
参考
v-htmlについて
v-htmlディレクティブは、指定された値を直接HTMLとして(文字列として)埋め込む機能を持っています。
書籍内ではmethods内で定義したpreviewメソッドをv-htmlで指定することにより、markdownで渡された値をhtmlのp要素として描画しているのです。
v-htmlディレクティブはコンパイルなどはせず、単純にhtmlを描画するだけなので、ユーザーデータなどを指定するとXSS(クロスサイトスクリプティング)の原因になるので注意。
参考
styleについて
スタイルについては、初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービス内だとscssを使っています。
今回私が作成したアプリについては、ほぼデフォルトのままなのですが、テキスト入力エリアだけ罫線をつけてCSSっぽくしてみました。
プレビュー画面の箇所についても、別ファイルでそれぞれのタグについてスタイルを適応させており、ちょっとエディタっぽい感じに仕上げています。
もしスタイルが反映されていない時は、ブラウザ自体のjsファイルのキャッシュかもしれないので、デベロッパーツールか** command + shift + r **でキャッシュをクリアしてみてください。
参考
最後に
今度参画する案件ではRailsのフロントエンドにReactを使っているとのこと。
でも、現状ではフロントエンドのフレームワークついてあまり知見がなかったので、比較的わかりやすいvue.jsについて学んでみようと思っていました。
そんなとき、初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービスに出会い、実際に作りながらコンポーネントの概念について学ぶことができました。
今回作成したのはSPAでしたが、せっかくなので今度はReactとRailsを組み合わせて、同じようなアプリを作ってみたいと思います。
ちょっとしたつぶやき
2018年のGWはひたすら家にこもって、プログラミングの勉強とYoutube見てました。
最近は嫁と一緒にゲーム実況をみるのにハマっていて、お気に入りはちゃあさんという同い年のYoutuberです(笑)