Backbone.jsでHello World （Backbone.Viewのサンプル）


# 前提

- 可能な限りES2015を使います

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

```html
<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>

```

# Hello Wolrd
## GIFアニメ
ボタンを押すと、alertを表示するサンプルです。

![out.gif](https://qiita-image-store.s3.amazonaws.com/0/15964/ab398510-3601-1238-8d38-17fc01129869.gif "out.gif")

## ソースコード
```html
<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>

<body>
  <div class="container">
    <button>say hello</button>
  </div>

  <script>
    const AppView = Backbone.View.extend({
      el: '.container',
      events: {
        'click button': () => alert('hello')
      }
    })
    new AppView
  </script>
</body>
```

## Viewクラスの動作解説
ユーザーイベントの処理を書く場合はViewを使います。
Viewは`Backbone.View.extend`の形式でカスタマイズしたコンストラクタを作ります。

### extendメソッド
extendメソッドは、Backbone.jsの提供する全モジュールで共通のAPIです。

```js
  // Set up inheritance for the model, collection, router, view and history.
  Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1902

第一引数に指定したオブジェクトでインスタンスプロパティを設定します。

```js
    // Set the prototype chain to inherit from `parent`, without calling
    // `parent`'s constructor function and add the prototype properties.
    child.prototype = _.create(parent.prototype, protoProps);
    child.prototype.constructor = child;
```

https://github.com/jashkenas/backbone/blob/master/backbone.js#L1890

## elプロパティ
既存のDOMにイベントハンドラーを設定したい時は、対象のDOMを`el`プロパティで設定します。

### elプロパティを設定した場合
初期化時に`$(el)`で取得したDOM要素を、elプロパティに設定しなおします。

```js
      this.$el = el instanceof Backbone.$ ? el : Backbone.$(el);
      this.el = this.$el[0];
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1280

`Backbone.$`はjQueryへの参照です。

```js
  Backbone.$ = $;
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L51

### elプロパティを設定しない場合

初期化時に作成したDOM要素を、elプロパティに設定します。

```js
        this.setElement(this._createElement(_.result(this, 'tagName')));
```

https://github.com/jashkenas/backbone/blob/master/backbone.js#L1355

## eventsプロパティ
イベントハンドラーはオブジェクトを使ったマップを指定できます。

```js
      for (var key in events) {
        var method = events[key];
        if (!_.isFunction(method)) method = this[method];
        if (!method) continue;
        var match = key.match(delegateEventSplitter);
        this.delegate(match[1], match[2], _.bind(method, this));
      }
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1307

バリューに関数を指定した場合は、その関数を使います。
文字列を指定した場合は、自インスタンスのメソッドを呼び出します。

```js
        if (!_.isFunction(method)) method = this[method];
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1309

## イベントハンドラーをバインド
作成したコンストラクタを呼び出すと、イベントハンドラーをバインドします。

コンストラクタから_ensureElementを呼び

```js
    this._ensureElement();
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1223

setElementを呼び

```js
        this.setElement(_.result(this, 'el'));
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1358

delegateEventsを呼びます。

```js
      this.delegateEvents();
```
https://github.com/jashkenas/backbone/blob/master/backbone.js#L1276

# alertをhtml上のメッセージ表示に変更

`click button`のイベントハンドラーを修正します。

```html
<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-min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.2/backbone.js"></script>
</head>

<body>
  <div class="container">
    <button>say hello</button>
    <span class="message"></span>
  </div>

  <script>
    const AppView = Backbone.View.extend({
      el: '.container',
      events: {
        'click button': function() {
          this.$el.find('.message').text('hello')
        }
      }
    })
    new AppView
  </script>
</body>
```

`$el`プロパティにはViewインスタンスがターゲットとするDOMの、jQueryオブジェクトが入っています。
`this`でViewインスタンスを参照して、プロパティを取得します。
アロー関数ではなく、無名関数を使います。

## jQueryを使わない場合

`el`プロパティにViewインスタンスがターゲットとするDOMが入っています。

```js
this.$el.find('.message').text('hello')

```
を

```js
this.el.querySelector('.message').innerText = 'hello'
```

と書いても良いでしょう。

# 関連記事

- [Backbone.jsのModel.fetch で RESTful API から情報取得](http://qiita.com/ledsun/items/d1146682e409c0687a1a)
- [Backbone.jsでModelに対応するViewをつくる](http://qiita.com/ledsun/items/dac6e7595ea9f28d30d2)
- [Bakcbone.jsとBrowserifyを一緒に使う](http://qiita.com/ledsun/items/e6703e703d4b3e7df7d7)