Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

前提

会社(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を明示的に取り回したい。

plaid
CXプラットフォーム「KARTE」の開発・運営、EC特化型メディア「Shopping Tribe」の企画・運営、CX特化型メディア「XD(クロスディー)」の企画・運営
https://plaid.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away