Angularそっちのけで、Vue.jsについて所感

Vue.js

を読んで触発されたので、自分も外見的に良いなと思ったポイントだけ書き留めてみます。さすがに実戦投入できていないので、そのあたりの精度は悪しからず。

サンプルコードの雰囲気

サンプルコードとか自分でちょっと触ってみたときの感触からは、以下のポイントが気に入りました。data-bidingsとかは前提として便利です。はい。

覚え切れそうな分量のAPI

脳みそちっちゃいので助かります。それに尽きる。

プロパティによる宣言っぽさ

Angularだとイベントハンドラ類を書くにも、$scopeに都度ハンドラを仕込んでいくのがあまり好きでないです。工夫で回避できそうですが、与えられたスタートが下記のような状態であることには変わりません。

angular.module('app', [])
  .controller('AbcCtrl', ['$scope', function($scope) {
    $scope.items = [1, 2, 3];
    $scope.onClick = function() {
      // わっちゃわっちゃ
    };
  }]);

スコープを跨いだ値の受け渡しなどを推奨しているかのようで、このようにベタっと書かれたコードを読んでいると、SAN値を持っていかれがちです。$.ready内に$(el).on(‘click’, function(){})が沢山並んでいるかのようなイメージが近いです。

その点、VueはBackboneに似ていてこんな感じでプロパティないしメソッドとして宣言するように書けます。

var view = Vue.extend({
  /* 前略 */
  data: {
    items: [1,2,3]
  },
  methods: {
    onClick: function (e) {
      // もっきゅもっきゅ
    }
  }
});

個人的には、これであれば文句ありません。適切なメソッドおよびスコープの分割を促してくれていますし、クラスベースのオブジェクト指向に共通する安心感が得られます。

自作ライブラリと似た所がある

完全に個人の都合です

前述の宣言的に書けるポイントについては、Backboneや拙作ライブラリはもちろん、Marionette.jsでも見られる傾向です。

自分はこのパターンを、正確にコピペしやすい・処理の独立性が高まりやすい・mixinで注入しやすい、と思われる非常に良いモノと考えています。

その流れから、拙作ライブラリとの共通点を見いだすことができました。

ViewModelであり再利用可能なComponentを登録しておくと、グローバルに利用することができます。粒度的には、AngularでいうElement Directive相当のイメージでしょうか。

// Vue
var parent = new Vue({
    template: '<div v-component="child"></div>',
    components: {
        child: Child
    },
    created: function () {
        this.$on('child-created', function (child) {
            console.log('new child created: ')
            console.log(child)
        })
    }
})

Vue.jsのコレと...

// Phalanx
var ListView = Phalanx.View.extend({
  components: {
    'moreBtn': ReadMoreBtnComponent
  },
  listeners: {
    'success moreBtn': 'renderMore'
  },
  renderMore: function(html) {
    this.$ui.list.append(html);
  }
});

Phalanxのコレ。なんか似てますね!(勢い)Componentで発生したイベントを、親のViewで受け取るような感じです。結構気に入っています。

総じてコンポーネントという名前と、再利用設計の面でちょっと似てる所があったため、親近感が沸いている次第です。

AngularにおいてはDI的な設計思想によるところもありそうですが、あるControllerの中にあるDirectiveから発生したイベントを、Controllerに伝える妥当なパターンがよくわかりません。そういう考えで作るべきじゃないのかもしれませんが、DirectiveがControllerやそのscopeのことを知っていないと、Directive外やDirective同士の連携面で再利用性が高まらないように感じています。

HTMLドリヴンなハンドリング

これはAngularにも共通して言えますが、HTML/TemplateにJS側の識別子を記述することで、JSがHTMLのセレクタを探しに行ったり、jQueryでいうTraversalメソッドを繰り返してアレコレするという負担が限りなく小さくなります。

<ul id="demo-2">
    <li v-repeat="users" v-component="user-profile"></li>
</ul>

一昔前のJSがHTMLに対して強固な依存を持っていたのを、HTMLがJSのメソッドや参照を呼び出すという関係に変えています。

逆にonclick=“foo()"の時代のごとく、HTMLにイベントハンドラを記述するのはどうなんだ、という件については、Why Listeners in HTML?を見ると、妥当性やメリットが説明されています。

Component志向

component - modular javascript frameworkは、パッケージマネージャー兼ビルドツールであり、Vue.jsはそのエコシステムに対応しています。

JSだけでなく、HTML/CSSもコンポーネントの構成要素と想定して

  1. パッケージの依存解決
  2. npm install的なインストール処理
  3. r.js main.js的なビルド処理

これらをまとめて実行してくれるのは、componentぐらいではないでしょうか。

業務的にも今年に入ってからcomponentの導入を真剣に検討していて、bowerは実行時の依存を解決してくれないし、browserifyはCSSとかスコープに入ってないし、という葛藤を繰り返しています。

ともかく、そういう事情も込みでVue.jsがComponentを志向しているのは、自分にとって歓迎すべき事実です。

Building Larger Apps - vue.jsを見ると分かりますが、全体的にvisionmedia (TJ Holowaychuk)推しな雰囲気が強いプロダクトです。 page.jsとかsuperagentとか。componentのエコシステムに入っている以上、さもありなんのチョイスですが、ともかくこの点についても個人的に好みです。

Angular優勢の時勢に一矢を...

報いてくれたら良いな、というAngular使えば使うほどtoo much(もちろん要件にもよるけど)に感じてしまう人でした。

  • Phalanx Backboneのラッパーライブラリ
  • Sarissa Phalanx+HandlebarsなSPAスケルトン

なんやかんや抽象化は自分でするのが1番楽しいですね。それでもVueはセンス良いと思いました。

以上、個人の感想でした。(予防線です)