2014年05月14日
普段はサーバサイドでゴリゴリPHPを書いているんですが、最近はJavaScriptを触る事も多いので、JavaScript界隈で話題になっているVue.jsを触ってみました。
Vue.jsの記事を見るとAngularJSと比べてる記事がほとんどだと思いますが、私が携わっているプロジェクトではBackbone.jsを中心に開発をしているので、Backbone.jsとVue.jsで実装した場合の違いを比べてみようと思います。
そもそもVue.jsとは?
いわゆるMV*的なJavaScriptフレームワークの一つだと言っていいと思います。
軽量AngularJSっていう感じのフレームワークですが、AngularJSに比べて比較的学習コストが低いフレームワークです。
大きな特徴としては
- MVVMアーキテクチャを採用している
- 強力なデータバインディング
- ディレクティブ
ってところだと思います。
MVVMアーキテクチャを採用している
Vue.jsではMVVMアーキテクチャを採用しています。
それに対してBackbone.jsは一般的なMVCアーキテクチャを採用しています(まあコントローラとよばれるオブジェクトはないんですけどね)
Model,View,ViewModelで構成されるアーキテクチャなんですが、MVCの派生系でもあります。
MVCアーキテクチャを知っている方なら、Model,Viewの役割はなんとなくわかると思うんですが、ViewModelとはなんだろうって方が多いのではないでしょうか?
私自身Backbone.jsを使っていたので最初はわかりませんでした。
「Viewから受け取った入力を適切な形に変換してModelに伝達する役目を持つ。すなわちViewとModelの間の情報の伝達と、Viewのための状態保持のみを役割とする要素である」
とwikipediaには記載されているのですが、まあViewとModelの間にあるオブジェクトって認識で良いかと思います。
ちなみにVue.jsではvueオブジェクトの中にModelとViewが入っています。
強力なデータバインディング
Backbone.jsでデータバインディングをする場合はBackbone.stickitを利用しなければなりません。しかもバインディングを開始したいタイミングで、メソッド実行しなければなりません。
1 2 3 4 5 6 7 8 9 |
var HogeView = Backbone.View.extend({ bindings:{ '#hoge-div': 'hoge' }, ... initialize: function() { this.stickit() } }) |
非常に直感的でないですよね。
それに対してVue.jsはデフォルトでバインディング機能をもっています。
AngularJS風にディレクティブで書いてあげればバインディングしてくれます。
個人的にはVue.jsのバインディングの方が分かりやすと思いました。
1 |
<textarea v-model="input"></textarea> |
1 2 3 4 5 |
new Vue({ data: { input: 'test' }, }) |
ディレクティブ
ディレクティブはBackbone.jsには無い概念ですね。AngularJS使っていればわかる概念だとは思いますが、私も最初はわかりませんでした。
どのような物かを私自身まだうまく説明できませんが、「DOM要素やその子要素に変形や特殊な振る舞いを割り当てるようにする」といった感じでしょうか?(違っていたらごめんなさい。
AungularJSのディレクティブの説明になってしまいますが、こちらサイトにディレクティブの説明が詳しく記載されています。
Vue.jsとBackbone.jsでコードの書き方を比べてみよう
さて、ここからはBackbone.jsのコードとVue.jsのコードを比べて行きましょう。
Markdownエディタ
Vue.jsのサンプルの一番最初に記載されている、MarkdownエディタについてBackbone.jsとの比較をしていきたいと思います。
まずはBackbone.jsのコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
var MarkdownModel = Backbone.Model.extend({ defaults: { text: "# hello" } }); var EditorView = Backbone.View.extend({ el: "#editor", events: { "keyup textarea": "onKeyUp" }, initialize: function(options) { this.listenTo(this.model, 'change', this.render); this.render(this.model); }, render: function(model) { this.$el.find("div").html(marked(model.toJSON().text)); return this; }, onKeyUp: function(e) { this.model.set({ text: $(e.currentTarget).val() }); } }); model = new MarkdownModel(); editorView = new EditorView({ model: model }); |
EditorViewでモデルとDOMを監視して、変更がったらそれぞれに通知するって感じですね。
単純な処理なんですが、コード量が多くなってしまいますね。それからどのようにViewオブジェクトを作ろうかとか、悩んでしまいます。
Backbone.jsに比べてVue.jsのJavaScriptのコードはものすごく少量となっています。
1 2 3 4 5 6 7 8 9 |
new Vue({ el: '#editor', data: { input: '# hello' }, filters: { marked: marked } }) |
ViewModelと強力なデータバインディングのおかげでコードすくなくなっちゃいますね。素晴らしい。
リスト形式な表示
さて次はリスト形式の表示するサンプルを見ていきましょう。
Vue.jsのサンプルにGithub Commitsというものがあるので、そのコードをBackbone.jsで実装した場合と比較してみましょう。
Backbone.jsの場合は標準でunderscore.jsのテンプレート使うのですが、Vue.jsのようなフィルタ処理ができないので、Viewオブジェクトで実行までしなければならないので、扱い辛いというか、どこでフィルタ処理をしているかわかり辛いです。(まあもっとマシな書き方はあると思いますが…)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// フィルタリング var filters = { truncate: function (v) { var newline = v.indexOf('\n') return newline > -1 ? v.slice(0, newline) : v }, formatDate: function (v) { return v.replace(/T|Z/g, ' ') } }; // コミット一覧ようのView var CommitView = Backbone.View.extend({ 'tagName': 'li', template: _.template($('#list-template').html()), render: function(model) { var data = model.toJSON(); data.commit.message = filters.truncate(data.commit.message); console.log(data.message) if (data.author !== null && typeof(data.author.date) !== 'undefined') { data.author.date = filters.formatDate(date.author.date); } this.$el.html(this.template(data)); return this; } }); |
一方Vue.jsではHTML側にフィルタリングの処理の実行を記述して、メソッド自体はjsのコード側に記載してあるので直感的に非常にわかりやすいですね。
1 2 3 4 5 6 7 8 9 |
filters: { truncate: function (v) { var newline = v.indexOf('\n') return newline > -1 ? v.slice(0, newline) : v }, formatDate: function (v) { return v.replace(/T|Z/g, ' ') } }, |
1 2 3 4 5 6 7 8 9 |
<li v-repeat="commits"> <a href="{{html_url}}" target="_blank" class="commit"> {{sha.slice(0, 7)}} </a> - <span class="message">{{commit.message | truncate}}</span> <br> by <span class="author">{{commit.author.name}}</span> at <span class="date">{{commit.author.date | formatDate}}</span> </li> |
最初は何となくディレクティブって使いすぎると微妙じゃない?ってのも思いましたが、慣れてくると結構良い物だったりします。
まとめ
Vue.jsは気軽に書けるので、書いてて気持ちがよいフレームワークだと思います。
ちなみにCoffeeScriptで書くとさらに気持ちよさが増します!
Backbone.jsやJQueryに慣れている人に取ってはディレクティブが若干使い辛いとか、覚えるのがめんどくさいとかあるかもしれませんが、AngularJSに行く前に触れておいてもいいフレームワークだと思いました。
今回は簡単な説明になってしまいましたが、これを機にBackbone.jsしか使った事無い人がVue.jsに興味をもったり使いはじめてくれると嬉しいです。
Vue.jsについて
Released under the MIT License
Copyright (c) 2014 Evan You
- Written by
- Ryota M.
- category:その他