Go to list of users who liked
More than 5 years have passed since last update.
Backbone.js入門 「Events」
閲覧上の注意
この記事で対象としているバージョン0.5.3は結構古いので注意してください。この記事でいえば、bind
は無くなり、現在ではon
やlistenTo
が使われています。
その他の割りと新しい情報はBackbone.js Advent Calendar 2012 などにあります。
(追記ここまで)
ネタ切れ感が否めないBackbone.js Advent Calendarですが、今回から何回かに分けて懇切丁寧な入門記事を書いていこうと思います。
以下のように書き進めていく予定です。
- Events
- View
- Model
- ViewとModelの連携
- Collection
- ViewとModelとCollectionの連携
- RouterとHistory
なおここで扱うBackbone.jsのバージョンは0.5.3です。
Backbone.js入門 「Events」
Backbone.jsのドキュメントを開くとまず最初に解説されているのがEvents
です。Events
を直接使うことは無いかも知れません。それというのもModel
Collection
Router
View
はEvents
を拡張しており、しかも用途に特化した様々な機能を持っているため、これらを使った方が便利だからです。
しかしながら、上記のオブジェクトを用いる中で間接的にEvents
を利用しているということができます。
Backbone.jsでのプログラミングは、このEvents
が提供するインタフェースを用いてオブザーバ・パターン を上手く使い、オブジェクト間の疎結合を促進することが基本的なコーディング方針です。
オブザーバ・パターン
JavaScriptに限らず、A.aが行われたら、B.aを行いたい、というような場面があります。
A.a=function(){// do somethingB.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 somethingthis.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
はオプションの引数で、callback
のthis
に束縛されます。context
は後述するEventsを用いる時の注意点 でもう一度扱います。
unbind([eventName], [callback])
他のオブザーバ・パターンの実装ではunregister と呼ばれることもあるメソッドで、既に束縛(bind )されているコールバック関数を解除することができます。eventName
とcallback
は両方省略可能で、両方省略すると全てのコールバック関数が解除されます。
trigger(eventName, [*args])
他のオブザーバ・パターンの実装ではnotify と呼ばれることもあるメソッドで、束縛されているコールバック関数を起動します。第二引数以降はそれぞれコールバック関数に引数として渡されます。
ここで、eventName
が"all" だった場合、このオブジェクトに束縛されている全てのコールバック関数が実行されます。
Eventsを用いる時の注意点
Events
に限らず、コールバック関数内ではthis
が何を指すのか気をつける必要があります。bind
において、context
を指定しなかった場合、コールバック関数内でthis
はSubject オブジェクトになります。つまり
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
を束縛する方法です。(紛らわしいですが、このbind
はEvents#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」です。お楽しみに
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme