157
159

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Backboneでデータバインディングを使ってMVVMをするフロントエンドアーキテクチャ

Last updated at Posted at 2013-10-31

前提

会社(Quipper)で今からこういう風にしたい、と宣言した社内ドキュメントを公開する。
枯れてるわけではない。

  • coffeescript
  • Backbone
  • Backbone.stickit (データバインディング)
  • Chapling.js(は、オマケなのでどうでもいいがサンプルコードはこう)

backbone.stickitは安心と信頼のNYT製。(実質Backbone作ってるDocumentCloudと一緒のところ?)
backbone.stickit

目的

データバインディングを全面的に使って再描画を最小限にし、コードの見通しをよくしたい。
モデルの役割を明示的にし、MVVMを導入する。

理想的なAPI

擬似コード


# ビューモデルの定義
class TopicViewModel extends Model
  defaults:
    title: '' # たぶんここでパラメータ名(と仮でもいいので初期値)を書いておくと見通しがよい

# topic.hbs
"""
<span class="title"></span>
"""

# !!! テンプレートはビューモデルにのみ依存してテンプレートを展開する
# getTemplateDataは可能な限り使わない

# controller
  ...
  show: ({topic_id})->
    # Collectionから紐付いたものをとってくる。Collectionの中身は事前に初期化されている。
    # Railsのコントローラに近いイメージでモデルを取得できるようにしておく
    # Modelの役割を本来の意味でのモデルに近づける

    topic = Topics.find {topic_id} #=> Backbone.Collectionはlodashのメソッドをmixinしているのでこういう風に書ける
    # fetchが必要かどうかはモデル次第。Topicに関しては最初に初期化しておきたい


    # 各種モデルを用いてビューモデルを組み立てる
    # ViewModelクラスはBockbone.Modelを継承しているがRESTを叩いたりはせず、ビューの振る舞いだけに興味がある
    topicViewModel = new TopicViewModel
      title: topic.title

    @compose 'topic', new TopicView model: topicViewModel

    # controllerが各種イベントに対するハンドラをもつ

    @subscribeEvent 'updateTopicTitle', (title) ->
      topicViewModel.set 'title', title #=> バインディングがあるのでビューも更新される

    # 仮にビューバインディングで対応できない系(大域に渡る処理)のものは、ある程度受け入れる
    @subscribeEvent 'changeContainerView', ($div) ->
      @$('.content').html $div

# 基本的にイベントは受け取るものは、コントローラで処理する
# コントローラが膨らむ場合は適宜モデルロジック、ビューロジックに移す


# view
# getTemplateDataは可能な限り使わず、ビューモデルにだけ依存する

class TopicView extends View
  # model -> TopicViewModel
  bindings:
    '.title': 'title'
    # ビューに特有な値はonSetなどを用いて生成する

  # ビューイベントをイベント名を翻訳して、コントローラへ向けて発火する
  render: =>
    super
    @stickit()

    # イベントハンドラはrender後に書く
    @delegate 'click', '.i-want-to-change-topic-title-to-hoge', => #雑…
      # コントローラが知るべきものはコントローラに向けてイベントを発火する
      @publishEvent 'updateTopicTitle', 'hoge'

これによって可能になるもの

  • サーバーサイドのモデルのコピーと、ビューに紐づくモデルを一貫させ、コードの見通しをよくする。
  • パラメータの書き換えを最小限に抑え、再描画を抑えパフォーマンスがよくなる
  • ビューの変更はビューモデルを通じて行う
  • テストはビューモデルの変更に対して行う(ビューモデルによって生成されるビューには感知しない) #=> DOMに触れずに済む
  • テンプレートはビューモデルに一意に依存するので、使えるパラメータが明示的になる

ビューモデルはフロントに近い存在なので、多少汚くてもいい。新しく作る概念なので、ある程度闇を引き受けてもらう。
いままでふわっとした扱いだったModelを明示的に取り回したい。

157
159
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
157
159

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?