JavaScript初級者がVue.jsで幸せになれたお話

こんにちは。制作部の平尾です。 前回はAnimate CC→Javascriptに変換してアニメーションを作ってみたお話をしたのですが、今回はVue.jsを触ってみたお話をしようと思います。

事例みたいなものはネット上にたくさん落ちているので、今回はJavaScript初級くらいでも簡単にできて便利だよ。ということをお伝えしたいと思います。

(この記事は mediba Advent Calendar 2016 の5日目です。)

Vue.jsとは

本家のサイトに書いてあるものをだいぶ雑に言い換えてみると、HTML(View)と何かしらのデータ(Model)と、それをコントロールするJS(ViewModel)を分けて書くための便利なフレームワークです。いわゆるMVVMでつくるためのフレームワーク。そしてそれがリアクティブなのがステキなところです。

幸せポイント①

初心者でもすぐ導入できちゃうくらい学習コストが低い。

JavaScript初級者からすると、何かのフレームワークを使うとなるとちょっと構えてしまうというか、React.jsてなに?(ポカーン)から始まるので、仕事の案件で採用するにはハードルが高いと思ってしまうのですが、Vue.jsはとっても簡単でわかりやすいので大丈夫です!基本的な機能だけなら半日で使えるようになると思います。

本家サイトのガイドもちゃんとしているし、日本語対応してくれているのもありがたい(ちょっと読みづらいけど)。

機能がシンプルなので、こう書くとこうなる。みたいなのが理解しやすいです。いろんなやり方をググったりしなくても、本家サイトのガイドを見るだけでだいたい作れちゃいます。

幸せポイント②

HTMLをいっぱい書かなくていい。

たとえば、何かのリストを作るとして、同じDOMを複製して中身だけを書き換えてることってよくありますよね。そんなときは、中身をdata化しておけば幸せになれます。

↓HTMLの方はこんな感じ

<ul id="vue-contents">
    <li v-for="item in items">{{ item.age }}歳の{{ item.name }}さん</li>
</ul>

↓data化しておく

var vueData = [
    {
        'name': 'ねこ',
        'age': 1
    },
    {
        'name': 'いぬ',
        'age': 2
    },
    {
        'name': 'うさぎ',
        'age': 3
    }
]

↓new Vueする

var vm = new Vue({
    el: '#vue-contents',
    data: {
        items: vueData
    }
    ~~~ 略 ~~~
})

↓実行されるとこうなる

<ul>
    <li>1歳のねこさん</li>
    <li>2歳のいぬさん</li>
    <li>3歳のうさぎさん</li>
</ul>

みたいなことです。 <li>をいっぱいつくらなくていいので幸せです。 たとえばバックエンドの何かのデータを使って<li>を量産するケースだと、ajaxで返ってきたJSONをVueのdataに入れるだけなので(自分でdata化する必要もない)、そういうときに幸せを感じます。

幸せポイント③

表示に関する条件分岐がHTMLの方に書ける。

たとえばユーザーのステータスによって表示を切り替えるみたいなケースも多いですよね。ログインとか。条件が複雑だったり、切り替える表示要素が多いとコード量が増えて煩雑になりがちですが、Vue.jsの場合はHTML側に条件が書けるので、シンプルになります。

↓ログイン/ログアウトボタンをこんな風に切り替えたり

<button v-if="isLogin">ログアウト</button>
<button v-else>ログイン</button>

(isLoginはVueのdataでtrue/falseを持っている想定)

↓0件表示を切り替えたり

<ul v-if="items.length > 0">
    <li v-for="item in items">{{ item.list }}</li>
</ul>
<div v-else>
<p>リストは0件です。</p>
</div>

↓アクティブのclassをつけたり消したり

<button :class="['nya', (item.active) ? 'is-on':'']">HOME</button>

(dataのactiveがtrueだとis-onが付け足されてclass="nya is-on"になる。falseのときはclass="nya"になる。)

この条件のときはこれとあれとそれを表示して…みたいなことをJSで書かなくても、HTML側つまりはView側に寄せることができるので幸せになれます。

幸せポイント④

dataをごにょごにょするのもラクちん。

これはdataのつくり次第でもあるのですが、たとえば何かの値段とかの数字をJSONで取得して、そのまま表示しようとしても'1000'とかだと、カンマで区切りたくなります。 そういうときは、いったんメソッドで処理させてreturnさせるだけです。

↓commaという自作メソッドの引数にdataの中身を渡す

<ul>
    <li v-for="item in items">{{ comma(item.price) }}円</li>
</ul>

↓たとえば値段がそのまま数字で返されるとして

var jsonData = [
    {
        'name': '商品名1',
        'price': 1000
    },
    {
        'name': '商品名2',
        'price': 2000
    },
    {
        'name': '商品名3',
        'price': 3000
    }
]

↓methodsに自作メソッドを書いてリターンさせる

var vm = new Vue({
    el: '#vue-contents',
    data: {
        items: jsonData
    },
    methods: {
        comma: function(price){
            return price.toString().replace(/(\d)(?=(\d{3})+$)/g , '$1,');
        }
    }
    ~~~ 略 ~~~
})

↓実行されるとこうなる

<ul><li>1,000円</li>
    <li>2,000円</li>
    <li>3,000円</li>
</ul>

ラクちんです。

オマケ(追記)

社内のVue.jsセンパイにアドバイスいただきました!こういう場合はmethodsよりもcomputedを使ったほうが良いそうです。methods=関数、computed=算出プロパティ。 本家サイトの算出プロパティ vs メソッドにちゃんと書いてありました。 methodsに登録していると、item.priceが変更されていようがいまいが、何かしらdataがアップデートされると毎回実行されてしまうけど、computedの方にすると、item.priceが変更されたときだけ実行されるみたいです。初回に実行した結果をキャッシュしているので、変更されていないときは即時に初回にキャッシュした結果を返してくれるみたい。Vue.jsさん優秀!

ただ、今回の例で扱っているdataが配列なので、直接item.priceの変更を検知させるためにはコンポーネントというのを使うことになります。それでこそVue.jsの恩恵が最大限活かされるくらいの機能なのですが、わりと長くなってきたのでまた次の機会に書こうと思います。

そして、社内にVue.jsセンパイがいて、さらに幸せになりました。

幸せポイント⑤

clickとかのイベントをbindするのもHTMLに書ける。

ユーザーがクリックしたら何かが起こるみたいなことは日常茶飯事で書いていると思うのですが、DOMを取得してイベントをbindして…の「DOMを取得して」を省略できます。条件分岐をViewに寄せたのと同じく、イベントもViewに寄せることができちゃいます。

↓DOMに直接v-onでイベントをbind

<button v-on:click="somethingToDo()">ボタン</button>

↓methodsにボタンがクリックされたときの処理を書く

~~~ 略 ~~~
methods: {
    somethingToDo: function(){
        // ボタンがクリックされたときの何かの処理
    }
}
~~~ 略 ~~~

JSに書くのはメソッドだけなのでスッキリして幸せです。

幸せポイント⑥

dataをアップデートするだけでDOMがアップデートされる。

個人的にはコレがいちばんの幸せポイントです。たとえば、何かのトリガーで表示要素を追加したくなったとすると、elementを作ってappendして…みたいなことになると思うのですが、Vue.jsならdataに追加するだけで勝手にelementを生成して追加してくれます。dataの中身をアップデートすれば、elementの中身もアップデートされます。リアクティブ万歳!

↓HTMLはこんな感じで

<p>全部で{{ items.length }}匹</p>
<ul>
    <li v-for="item in items">{{ item.age }}歳の{{ item.name }}さん</li>
</ul>

↓dataは最初のサンプルと同じくこんな感じだとします

var vueData = [
    {
        'name': 'ねこ',
        'age': 1
    },
    {
        'name': 'いぬ',
        'age': 2
    },
    {
        'name': 'うさぎ',
        'age': 3
    }
]

↓実行されるとこうなる

<p>全部で3匹</p>
<ul><li>1歳のねこさん</li>
    <li>2歳のいぬさん</li>
    <li>3歳のうさぎさん</li>
</ul>

このあと、何かのタイミングでうさぎさんをはりねずみさんにして、ふくろうさんも追加したくなるイベントが発火したら、配列をアップデートします。

vueData[2].name = 'はりねずみ';
vueData.push({
    'name': 'ふくろう',
    'age': 10
})

↓配列がアップデートされたタイミングで勝手にこうなります

<p>全部で4匹</p>
<ul><li>1歳のねこさん</li>
    <li>2歳のいぬさん</li>
    <li>3歳のはりねずみさん</li>
    <li>10歳のふくろうさん</li>
</ul>

配列の中身を更新しただけなのに!ラクちんすぎる!

まとめ

シンプルで自由度が高くて扱いやすいのが何より幸せ。

本当はポイントを5個にしたかったのですが、勢いで6個になってしまいました。

設計がとても下手くそで煩雑になりがちな私にとっては、MVVMを学ぶのにもいい機会になりました。

今回はVue.jsの超初歩的なところしか書いていませんが、ミックスインとかコンポーネントの機能を使ったりするとさらに幸せになれそうな予感なので、もう少し踏み込んだ使い方をしてみたくなりました。 AngularJSやReact.jsあたりはちょっとハードルが高そうですが、Vue.jsは本当にシンプルで扱いやすくて簡単なので、是非みなさんもチャレンジしてみてください。 ここまでお付き合いいただいてありがとうございました。

オマケというか告知

Vue.jsを使ってつくったわたしねこ。というサービスをリリースしました!(まだベータ版ですが…)

ひたすらねこさんたちが癒してくれますので、ぜひ会員登録して「いいにゃ」してくださいニャー(●ↀωↀ●)✧

よろしくお願いします!