フロントエンド初心者がvue.jsを【初めてのシングルページアプリケーション 】で学んでみたら、めちゃくちゃ捗った件

vue.jsアイキャッチ vue.js

どうも、フリーランスエンジニアのYutaです。

今Webエンジニア界隈のTwitterで話題になっている初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービスってご存知ですか?

たった500円でフロントエンドのフレームワークの一つであるvue.jsについて、実際にマークダウンのメモアプリを作りながら学ぶことができるという。

Vue.jsの入門書を書店で買うと2000円以上はするのに、それに負けじ劣らずの濃い内容なのも魅力です。

著者ワタナベさん曰く、

とのことなので、熱い想いに答えるべく実際に購入してアプリを作成!

作成したアプリ

petit-notes

Githubリポジトリ

yuta-ushijima/petie-notes
Contribute to petie-notes development by creating an account on 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

でアプリケーションサーバーを立ち上げると編集画面に遷移しなくなるので、該当箇所をコメントアウトする必要があるので注意してください。

参考サイト

Vagrant環境でwebpack-dev-serverを動かしたい - Qiita
# 背景 Ruby on Rails 5.1.rc1 で webpacker を使ってみたかったので、手始めに (h...
vagrant + firebase loginでブラウザ認証が失敗する場合の解決方法 - Qiita
## こんな時 vagrantで立ち上げたVM上でfirebase login => ブラウザ認証がしたい しかし… ```sh $ firebase login ? Allow Firebase to collect anony...

firebaseを使ったGoogleログインを実装する際のデータの流れ

googleログイン機能を実装する際に、出てきたthisメソッドについてこんがらがってしまったため、知識を整理するべくワタナベさんに質問してみました。

Yuta
Yuta

こんにちは!
初歩的な質問で恐縮ですが、お手すきの際にご回答いただけたら嬉しいです!

モモンガ本の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コンポーネント」と言えるのでちょっとややこしいですね笑

Yuta
Yuta

ありがとうございます!
ちなみに、インスタンスについて以下のサイトを参考にしたのですが、app.vueのインスタンスって、ここでいうルートvueインスタンスとは別物ですか?

そうですね、別物です!
上のthisはapp.vueのコンポーネントインスタンス自体で

ルートインスタンスはmain.jsでnewした際のインスタンスになりますね。

Yuta
Yuta

なるほど、ちょっとこんがらがっていました(笑)
ということは、データの流れとしては、

1.ログインボタンが押されることでapp.vueでコンポーネントのインスタンスが作成される
2.created関数が発火
3.firebase.auth(),onAuthStateChagedでログイン情報をチェック
4.ログインされていたら、”user=>”の部分でuserという変数にユーザー情報を格納(アロー関数?)
5.ifの引数にuser変数を指定して、ユーザー情報の有無によってapp.vueインスタンス(this)をisLoginにture/falseとして格納

このような認識であってますか?

あっています!

インスタンスの概念はvue.jsだけでなくオブジェクト指向のプログラミング言語であれば必ず出てくるものです。

???となってしまった方は、以下のサイトで概要を掴んでみてください。

インスタンス化 (instantiation)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
用語「インスタンス化 (instantiation)」の意味を何となく説明しています。

ディレクティブとは

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']

参考

コンポーネントの基本 — Vue.js
Vue.js - The Progressive JavaScript Framework
Vue.jsのコンポーネント入門 - Qiita
# 規模が大きくなってきたらコンポーネント化しよう Vue.jsを一番シンプルに書くとこんな感じ。 ```js:main.js {{ message }} var app = n...

v-modelについて

v-modelを使うことで双方向データバインディング機能を実装することができます。双方向というのは、テンプレートで入力された値(テキスト入力部分)とデータオブジェクト(dataで定義されたメソッド)を紐付けることで互いの値が即座に更新されるというものです。

書籍内ではこのv-modelにmarkdownを指定することによって、データオブジェクトにテキストエリアで入力された値を格納しています。(データオブジェクト内でmarkdownを空文字にしているのはそのため)

markdownに格納された値をpreviewメソッドにthisで渡すことでプレビュー機能を実装していることになります。

参考

フォーム入力バインディング — Vue.js
Vue.js - The Progressive JavaScript Framework
Vue.jsサンプルコード(04)双方向データバインディングを使ってみる
前の記事: 01〜03: Hello World・デバッグ・結果の表示 次の記事: 05: 複数のinputに同じ変数を割り当てるとどうなる? 04. 双方向データバインディングを使ってみる inputなどのHTMLタグにv-model属性を追加すると双方向データバインディングが有効になる(公式記事)。 {{a}} ポ

v-htmlについて

v-htmlディレクティブは、指定された値を直接HTMLとして(文字列として)埋め込む機能を持っています。
書籍内ではmethods内で定義したpreviewメソッドをv-htmlで指定することにより、markdownで渡された値をhtmlのp要素として描画しているのです。

v-htmlディレクティブはコンパイルなどはせず、単純にhtmlを描画するだけなので、ユーザーデータなどを指定するとXSS(クロスサイトスクリプティング)の原因になるので注意。

参考

クロスサイトスクリプティング (XSS)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
用語「クロスサイトスクリプティング (XSS)」の意味を何となく説明しています。
テンプレート構文 — Vue.js
Vue.js - The Progressive JavaScript Framework

styleについて

スタイルについては、初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービス内だとscssを使っています。

今回私が作成したアプリについては、ほぼデフォルトのままなのですが、テキスト入力エリアだけ罫線をつけてCSSっぽくしてみました。

petit-notes

プレビュー画面の箇所についても、別ファイルでそれぞれのタグについてスタイルを適応させており、ちょっとエディタっぽい感じに仕上げています。

ぷちノートプレビュー

もしスタイルが反映されていない時は、ブラウザ自体のjsファイルのキャッシュかもしれないので、デベロッパーツールか** command + shift + r **でキャッシュをクリアしてみてください。

参考

CSS で textarea に罫線を入れてノートっぽくしてみよう
CSS3 の gradient をうまく使えば画像を使わずに罫線を表示することができます. Runstant Demo 今回作ったサンプルです. Code 主な CSS 部分です. textarea { width: 30rem; height: 30rem; background: hsl(60,

最後に

今度参画する案件ではRailsのフロントエンドにReactを使っているとのこと。

でも、現状ではフロントエンドのフレームワークついてあまり知見がなかったので、比較的わかりやすいvue.jsについて学んでみようと思っていました。

そんなとき、初めてのシングルページアプリケーション Vue.jsとFirebaseで作るミニWebサービスに出会い、実際に作りながらコンポーネントの概念について学ぶことができました。

今回作成したのはSPAでしたが、せっかくなので今度はReactとRailsを組み合わせて、同じようなアプリを作ってみたいと思います。

ちょっとしたつぶやき

2018年のGWはひたすら家にこもって、プログラミングの勉強とYoutube見てました。

最近は嫁と一緒にゲーム実況をみるのにハマっていて、お気に入りはちゃあさんという同い年のYoutuberです(笑)

ちゃあ/chaa's - YouTube
基本的にゲーム実況をメインに活動しています! 毎日楽しくマリオメーカーを実況しています(´・ω・`) よくオネエ口調をいって勘違いされますがホモ、バイではありません!! 好きな性別は女性一択なのでご注意を!!!!