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
<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でそれぞれの定義を一ファイルで行っている。これを細かく作っていけば、ファイルがばらばらにならずに小さいコンポーネントを個別に作成していくことができる。
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