4
3

More than 5 years have passed since last update.

Backbone.jsでModelに対応するViewをつくる

Last updated at Posted at 2016-03-24

準備

依存ライブラリ

Backbone.jsはjQueryとunderscoreに依存しています。
準備を簡単にするために、各ライブラリをCDNから取得します。

<head>
  <script src="https://code.jquery.com/jquery-2.2.2.js" integrity="sha256-4/zUCqiq0kqxhZIyp4G0Gk+AOtCJsY1TA00k5ClsZYE=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.2/backbone.js"></script>
</head>

RESTful API

typicode/jsonplaceholder: A simple fake REST API serverを使います。

npm install -g jsonplaceholder
jsonplaceholder

http://localhost:3000/posts/1 からリソースを取得します。

完成画面

スクリーンショット 2016-03-24 10.40.24.png

ES2015を使っています。

  • Const
  • Arrow Functions
  • Template Strings
  • Enhanced Object Literals

次のブラウザで動きます。

  • Google Chrome 49.0.2623.87
  • Firefox 44.0.2

Safari 9.0.3では動きません。

ソースコード

<head>
  <script src="https://code.jquery.com/jquery-2.2.2.js" integrity="sha256-4/zUCqiq0kqxhZIyp4G0Gk+AOtCJsY1TA00k5ClsZYE=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.2/backbone.js"></script>
  <style>
    body {
      font-size: 1.1em;
    }

    input {
      font-size: 100%;
      width: 700px;
    }

    textarea {
      font-size: 100%;
      height: 100px;
      width: 700px
    }

    button {
      font-size: 100%;
    }
  </style>
</head>

<body>
  <script>
    const PostModel = Backbone.Model.extend({
        url: 'http://localhost:3000/posts/1'
      }),
      PostView = Backbone.View.extend({
        events: {
          'click button': function() {
            this.model
              .set({
                title: this.$('input').val(),
                body: this.$('textarea').val()
              })
              .save()
          }
        },
        initialize() {
          this.model.on('change', () => this.render())
        },
        render() {
          const json = this.model.attributes,
            html =
            `
              <div>title:</div>
              <input value="${json.title}">
              <div>body:</div>
              <textarea>${json.body}</textarea>
              <div>
                <button>押す</button>
              </div>
            `

          this.$el.html(html)
        }
      }),
      postModel = new PostModel(),
      postView = new PostView({
        model: postModel
      })

    $('body').append(postView.$el)
    postModel.fetch()
  </script>
</body>

解説

PostModel

Backbone.js の Model.fetch で RESTful API から情報取得 と同じです。
urlをローカルアドレスに変更しています。

PostView

eventsハッシュマップ

events: {
  'click button': function() {
   this.model
    .set({
       title: this.$('input').val(),
       body: this.$('textarea').val()
    })
    .save()
  }
},

ボタンクリック時のイベントハンドラーを定義します。
thisでPostViewインスタンスを参照するため、アロー関数は使えません。

backbonejs.org

views with declarative event handling

の部分です。

initialize関数

initialize() {
  this.model.on('change', () => this.render())
},

初期化処理です。
モデルのchangeイベントに応じてrender関数を実行します。
アロー関数なので、thisはinitialize関数実行時のthis、つまりPageViewのインスタンスです。

次のように、無名関数を使うと

this.model.on('change', function (){ this.render() })

thisはchangeイベントのコールバック関数実行時のthis、つまりPageModelのインスタンスになり上手くうごきません。
http://backbonejs.org/#View-extend では

this.listenTo(this.model, "change", this.render)

を推奨しています。

If the view defines an initialize function, it will be called when the view is first created.

initialize関数はインスタンス生成時に実行されます。より正確には、

var View = Backbone.View = function(options) {
  this.cid = _.uniqueId('view');
  _.extend(this, _.pick(options, viewOptions));
  this._ensureElement();
  this.initialize.apply(this, arguments);
};

コンストラクタの最後で実行されます。

initialize: function(){},

initialize関数が定義されていない場合は空関数が実行されます。

render関数

render() {
  const json = this.model.attributes,
    html =
    `
      <div>title:</div>
      <input value="${json.title}">
      <div>body:</div>
      <textarea>${json.body}</textarea>
      <div>
        <button>押す</button>
      </div>
    `

  this.$el.html(html)
}

this.model.attributesからモデルの値を取得します。
Template Stringsを使ってhtml文字列を作成します。
jQuery.htmlを使って、自身の要素にhtml文字列を追加します。

main処理

postModel = new PostModel(),
postView = new PostView({
  model: postModel
})

$('body').append(postView.$el)
postModel.fetch()

PostModelのインスタンスを作ります。
modelとしてPostModelのインスタンスを指定して、PostViewのインスタンスを作ります。
PostViewのインスタンスの$elプロパティに、作成したDOMのjQueryオブジェクトが入っています。
bodyに追加します。
PostModelのインスタンスのfetchメソッドで、RESTful APIから値を取得します。

関連記事

4
3
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
4
3