Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
273
Help us understand the problem. What is going on with this article?
@yuku_t

Backbone.js入門 「Events」

More than 5 years have passed since last update.

閲覧上の注意

この記事で対象としているバージョン0.5.3は結構古いので注意してください。この記事でいえば、bindは無くなり、現在ではonlistenToが使われています。

その他の割りと新しい情報は Backbone.js Advent Calendar 2012 などにあります。

(追記ここまで)


ネタ切れ感が否めないBackbone.js Advent Calendarですが、今回から何回かに分けて懇切丁寧な入門記事を書いていこうと思います。
以下のように書き進めていく予定です。

  1. Events
  2. View
  3. Model
  4. ViewとModelの連携
  5. Collection
  6. ViewとModelとCollectionの連携
  7. RouterとHistory

なおここで扱うBackbone.jsのバージョンは0.5.3です。

Backbone.js入門 「Events」

Backbone.jsのドキュメントを開くとまず最初に解説されているのが Events です。
Events を直接使うことは無いかも知れません。それというのも Model Collection Router ViewEvents を拡張しており、しかも用途に特化した様々な機能を持っているため、これらを使った方が便利だからです。
しかしながら、上記のオブジェクトを用いる中で間接的に Events を利用しているということができます。
Backbone.jsでのプログラミングは、この Events が提供するインタフェースを用いて オブザーバ・パターン を上手く使い、オブジェクト間の疎結合を促進することが基本的なコーディング方針です。

オブザーバ・パターン

JavaScriptに限らず、A.aが行われたら、B.aを行いたい、というような場面があります。

A.a = function () {
    // do something
    B.a();
};

これで問題無いように思えますが、AはBがaメソッドを持っていることを知っていなければなりませんし、後になってC.aを追加したくなるかも知れません。それに、動的にB.aが実行されるかどうかを切り替えたい場合は、さらにゴチャゴチャしてきます。
このような場面でオブザーバ・パターンを用いることで、プログラムの見通しをよくすることができます。(Aのようなオブジェクトを 出版者Subject 、Bを 購読者Observer と呼びます)

A.bind("doA", B.a);  // A に対して doA が trigger されたら B.a を実行する
A.a = function () {
    // do something
    this.trigger("doA") // => B.a が実行される
}

あとからC.aも実行したくなったら A.bind("doA", C.a) を実行すればよい訳です。

Eventsの使い方

ここでAを Events を用いて定義すると以下のようになります。

A = {};
_.extend(A, Backbone.Events);

Events を拡張したAにはbind, unbind そして trigger の3つのメソッドが追加されています。

bind(eventName, callback, [context])

他のオブザーバ・パターンの実装では register と呼ばれることもあるメソッドで、A.trigger(eventName) によって callback が起動されるようになります。context はオプションの引数で、callbackthis に束縛されます。context は後述する Eventsを用いる時の注意点 でもう一度扱います。

unbind([eventName], [callback])

他のオブザーバ・パターンの実装では unregister と呼ばれることもあるメソッドで、既に束縛( bind )されているコールバック関数を解除することができます。eventNamecallback は両方省略可能で、両方省略すると全てのコールバック関数が解除されます。

trigger(eventName, [*args])

他のオブザーバ・パターンの実装では notify と呼ばれることもあるメソッドで、束縛されているコールバック関数を起動します。第二引数以降はそれぞれコールバック関数に引数として渡されます。

ここで、eventName"all" だった場合、このオブジェクトに束縛されている全てのコールバック関数が実行されます。

Eventsを用いる時の注意点

Events に限らず、コールバック関数内では this が何を指すのか気をつける必要があります。
bind において、context を指定しなかった場合、コールバック関数内で thisSubject オブジェクトになります。つまり

B = {
    name: "B",
    b: function () { console.log(this.name) };
}
A.name = "A";
A.bind("foo", B.b);
A.trigger("foo"); // => "A"

これは意図しない動作でしょう。ここで、this をBにする方法はいくつかあります。まずは、context を使う方法です

A.bind("foo", B.b, B);
A.trigger("foo"); // => "B"

もう一つは、_.bind を使って事前に this を束縛する方法です。(紛らわしいですが、この bindEvents#bind とは全くの別物です)

B.b = _.bind(B.b, B);
A.bind("foo", B.b);
A.trigger("foo"); // => "B"

この方法の利点は、金輪際、どのような状況で呼び出されようと、B.b() が "B" と出力するようになることです。B.b を何度もコールバック関数として使う場合は、先に _.bind しておくとよいでしょう。
しかしながら、Bのメソッドが増えてくると、いちいち _.bind を呼ぶのが面倒です。

B = {
    b1: function () {},
    b2: function () {},
    b3: function () {},
    b4: function () {},
    b5: function () {},
    b6: function () {},
    b7: function () {},
    b8: function () {},
    b9: function () {},
    b10: function () {}
};
B.b1 = _.bind(B.b1, B);
// ...  面倒
B.b10 = _.bind(B.b10, B);

こういう場合は _.bindAll が便利です。_.bind を10回呼ぶ代わりに、次のように書くことができます。

_.bindAll(B, "b1","b2","b3","b4","b5","b6","b7","b8","b9","b10");

次回は

次回は「View」です。お楽しみに


  1. Backbone.js入門 Events
  2. Backbone.js入門 MVC
  3. Backbone.js入門 View
  4. Backbone.js入門 Model
  5. Backbone.js入門 ViewとModelの連携
  6. Backbone.js入門 Collection
  7. Backbone.js入門 ViewとModelとCollectionの連携
  8. Backbone.js入門 RouterとHistory
273
Help us understand the problem. What is going on with this article?
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
yuku_t
FLYWHEEL社でソフトウェアエンジニアをしています。昔はIncrements社最初の従業員としてQiitaを開発したりCTOやったりしていました。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
273
Help us understand the problem. What is going on with this article?