Rails5.1＋Vueで何か作る前の基礎勉強


Railsの5.1からwebpackerが導入されて、ReactやAngular、Vueなどのフロントのフレームワークの導入がものすごく楽になった。

Rails5.1とvue.jsの2.xで何か作ってみようと思ったので、その前にVue.jsとRails5.1の基礎について軽くまとめておくことにした。自分用のまとめメモ。


# Rails5.1でVueを導入する

## 必要なものを事前にインストールしておく

まずはRailsを最新バージョンにしてください。前提としてRubyのバージョンが2.2.2以上であることを確認してください。

```
$ gem update rails
```


webpackerではYarnを利用します。Yarnがインストールされていない場合は先にインストールしましょう。
macであればbrewで一発です。出来ない場合は`brew update`を先にしましょう

```
$ brew install yarn
``` 

## プロジェクトの作成

```
$ rails new test_project --webpack=vue
```

上記のコマンドを入力すると、プロジェクト作成時にVue.jsもインストールされます。さらに、Webpackerと呼ばれるRailsにwebpackを簡単に導入できるgemもインストールします。（webpackはjsをビルドするツールです）


準備はこれだけです。
フロントの設定はこれだけですべてインストール完了


## ディレクトリ

今までのRailsと違ってディレクトリが色々と増えています。

`app/javascript`というディレクトリ以下に、Vueのファイルが入っている。

```
app/javascript/
└── packs
    ├── app.vue
    ├── application.js
    └── hello_vue.js
```


他にも`config/webpack`以下にはwebpackの設定ファイルが入っていたり、Railsがデフォルトでフロントのディレクトリを作成してくれる。めちゃくちゃ楽。

```
config/webpack
├── configuration.js
├── development.js
├── loaders
│   ├── assets.js
│   ├── babel.js
│   ├── coffee.js
│   ├── erb.js
│   ├── sass.js
│   └── vue.js
├── production.js
├── shared.js
└── test.js
```


RailsのVueの中身を見る前に先に、Vue.jsの基礎を書いておく。



# Vue.jsの基礎

VueはReactやAngularに比べるとものすごく軽い。学習コストがかなり低くて実装も簡単にできる。Angularはフルスタックなので重いし、ReactはFluxの概念を覚えるのがセットのようなものだから、学習コストが結局高くなる。

だからサッと何かを作りたいときなどにはかなりVue.jsはおすすめだ。もしくは大規模な場合でも、軽量なので自分でゴリゴリにカスタマイズできるので良い。


## 最小のVueの構成

```
<!DOCTYPE html>
<html>
  <head>
    <title>FrescobolScore</title>
    <script src="https://unpkg.com/vue"></script>
  </head>

  <body>
    <div id="app">
      {{ message }}
    </div>

    <script type="text/javascript">
      var app = new Vue({
        el: '#app',
        data: {
          message: 'Hello Vue!'
        }
      })
    </script>
  </body>
</html>
```

（上記はCDNをヘッダーで読み込んでいる）

見てすぐ理解できると思う。`app`を紐付けて単純にVueのオブジェクトを作成しているだけだ。`data:`で定義した変数をhtml内で使用することができる。


### v-for

```javascript
<div id="app">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>

<script type="text/javascript">
var app = new Vue({
  el: '#app',
  data: {
    todos: [
      { text: 'Learn JavaScript' },
      { text: 'Learn Vue' },
      { text: 'Build something awesome' }
    ]
  }
})
</script>
```

ループしたいときも単純で`v-for`ディレクティブを使用するだけである。


### v-on

```
<div id="app">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>

<script type="text/javascript">
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})
</script>
```

`v-on`ディレクティブを設定すると、javascriptのイベントを登録できる。今回はクリックしたときのイベントを設定している。また、`methods`にはhtml内で使用できるメソッドを指定できる。

`data:`で設定された値は、`methods:`内でも使用できるので、動的にメッセージを変更することができる。


### v-model


```
<div id="app">
  <p>{{ message }}</p>
  <input v-model="message">
</div>

<script type="text/javascript">
var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})
</script>
```

`v-model`ディレクティブを使用すると、テキストボックスなどと簡単にバインディングすることができる。テキストボックスで変更した値がすぐにmessageに反映される


### コンポーネントの作成

vueではコンポーネントという概念が非常に大切。小さく部品ごとに分けることによって再利用しやすいようにできる。

```
<div id="app">
  <ol>
    <todo-item v-for="item in groceryList" v-bind:todo="item"></todo-item>
  </ol>
</div>

<script type="text/javascript">
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})
var app = new Vue({
  el: '#app',
  data: {
    groceryList: [
      { id: 0, text: 'Vegetables' },
      { id: 1, text: 'Cheese' },
      { id: 2, text: 'Whatever else humans are supposed to eat' }
    ]
  }
})
</script>
```

`Vue.component`でtodo-itemというコンポーネントを作成している。`template`でその中身を定義している。コンポーネントを利用するときは`<todo-item></todo-item>`のようにタグを使用するだけ。

呼び出し側と呼び出し元の値の受け渡しを`props`に定義して行っている。`v-bind:todo`として、`props`の値にバインドさせているのがわかる。

あと単純に`groceryList`の中身をループさせて、`todo-item`というコンポーネントを何度も再利用している。


```
<div id="app">
  <ol>
    <li>Vegetables</li>
    <li>Cheese</li>
    <li>Whatever else humans are supposed to eat</li>
  </ol>
</div>
```

生成されたhtmlは上記のようになる。`template`で定義された`<li>{{ todo.text }}</li>`が連続で表示されているだけ。




## Railsに作成された`app/javascript/packs`内のファイルを見る

再びRailsの話し。ここで見慣れない`.vue`という拡張子のファイルがあると思う。

```
app/javascript/
└── packs
    ├── app.vue
    ├── application.js
    └── hello_vue.js
```

これはVueの単一ファイルコンポーネントというもので、一つのファイルにhtmlやjs, cssを書けるようにしているものだ。

ファイルの中身は以下のようになっている。


```
<template>
  <div id="app">
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      message: "Hello Vue!"
    }
  }
}
</script>

<style scoped>
p {
  font-size: 2em;
  text-align: center;
}
</style>
```

template、script、style scopedでそれぞれの定義を一ファイルで行っている。これを細かく作っていけば、ファイルがばらばらにならずに小さいコンポーネントを個別に作成していくことができる。


```hello_vue.js

import Vue from 'vue'
import App from './app.vue'

document.addEventListener('DOMContentLoaded', () => {
  document.body.appendChild(document.createElement('hello'))
  const app = new Vue(App).$mount('hello')

  console.log(app)
})
```

`hello_vue.js`は先程の`app.vue`を読み込んで、Vueのオブジェクトを作成している。
先程までは`el`を使って定義していたが、今回は`Vue(App).$mount('hello')`を使って作成している。

$mountについては公式サイトを参照
https://jp.vuejs.org/v2/api/#vm-mount



```
<%= javascript_pack_tag 'hello_vue' %>
```

上記の2ファイルが定義されているので、あとはhtml内で呼び出すだけ。`rails g controller home index`などで適当なコントローラーを作って、viewにスクリプトタグを記載する

### ビルドして起動


```
$ bin/webpack
```

あとはwebpackを使用して、javascriptをビルドする

```
$ rails s
```

あとはサーバを起動して、localhost:3000を見れば画面に`Hello Vue!`が表示されているはず。


## 所感

めちゃくちゃ簡単だった。これはすごい。一気に開発が楽になるし、何より共通のフロントのディレクトリ構造があるっていうのが素晴らしい。

これからRails+webpack+Vueを利用して何か作ろうと思う。環境構築に手間がかからないって最高だな。


## 参考


単一ファイルコンポーネント（公式
https://jp.vuejs.org/v2/guide/single-file-components.html


Vue.js 2.0 の Single File Components を試してみる
http://qiita.com/kazusa-qooq/items/f6f8baf08b61f49d8809