データバインディングについてVue.jsと Backbone.stickitを比較する

これは会社でvue.jsを採用を説得するための資料なのでstickitを罵倒する

vue.js http://vuejs.org/

backbone.stickit http://nytimes.github.io/backbone.stickit/

Backbone.stickitとVue.jsの比較

「#menuを押したら右に100px動く」みたいなコードを書いてみるとする。 template関数はJadeテンプレートを展開する関数だと思ってほしい

Backbone.stickit の場合

class MenuView extends Backbone.View
  initialize: ->
    @model = new Backbone.Model()
    @render()

  render: ->
    @$el.html template("""
      #menu.js-open
    """)
    @stickit()

  bindings:
    '.js-move':
      observe: 'positionX'
      update: ($el, model, val) ->
        $el.css 'left', val

テストケース

it 'should move to left 100', ->
  menu = new MenuView
  menu.move()
  expect(menu.model.get 'positionX').eq 100

問題

  • Backbone.stickitにとっては、DOMが観測主体である
  • 'on chagnge' に依存して発火するので、ネストした値は同期できない(Backbone.Modelの問題)
  • Viewとテンプレートにまたがってやや複雑な手続きになる
  • updateの中でjQueryを記述するのは自由度は高いがメンテナビリティが低い

Vue.jsの場合

Menu = Vue.extend
  template:
    template """
      #menu(style="left: {{positionX}}px" v-on="click: move")
    """
  data:
    positionX: 0
  methods:
    move: ->
      @$data.positonX = 100

テストケース

it 'should move to left 100', ->
  menu = new Menu
  menu.move()
  expect(menu.$data.positionX).eq 100

このとき、Menuのインスタンスはビューモデルだが、Backbone.View相当のものはViewModelの下に完全に従属していると言って良い。

メリット

  • 記述ステップが短い(手続き的ではなく宣言的である)
  • ViewModel(Vue)がViewを隠ぺいする
  • テンプレートで余計な装飾が不要で直感的

Viewが隠蔽されることで、見た目上、ピュアなJavaScriptオブジェクトだけを相手にしてコードが書けるようになる。これによって複雑怪奇なDOMの相手を極力減らすことができる。

経験上、DOMとViewクラスを完全に分離して再利用できたことは一度もない。凝集性の重視して密結合することで見通しをよくするのはアリだと思う。

何が言いたいか

Viewで扱うパラメータをViewModelのパラメータ化して隠蔽したい。get/setがカッコ悪い。バインドされてる値を特殊なものだとして扱いたくない。

Angularと比べた時のメリット

Angular巨大すぎ。学習コスト高すぎ。DSL汚すぎ。(個人の見解です)。 少なくとも途中からの移行は不可能なので考えない。

中の人から翻訳記事書いて欲しいとのこと

翻訳記事書いた https://gist.github.com/mizchi/9066737