Ember.jsのデータバインディングの仕組みについて説明します。
Ember.Objectクラスがデータバインディングの機能を提供しています。
Ember.View、Ember.Controllerなどの、Ember.jsアプリケーションを構成するクラスは Ember.Object クラスを継承しているので、それらのクラスではデータバインディング機能を利用できます。
(Ember.Objectクラスのインスタンスを作るには、Ember.Object.create()メソッドを使います。
Ember.Objectクラスを継承したクラスを作るには、Ember.Object.extend()メソッドを使います。)
Ember.jsはデータバインディングのために、プロパティ、オブザーバ、バインディングという機能を提供しています。それぞれ説明します。
プロパティ
他のメンバを参照するメンバを定義します。参照先に、他のプロパティを指定することもできます。
参照先のメンバが更新されると、プロパティの値も更新され、プロパティを参照しているプロパティ/オブザーバ/バインディングにも更新を通知します。
var Multiplier = Ember.Object.extend({
lhs: 6,
rhs: 7,
answer: function () {
return this.get('lhs') * this.get('rhs');
}.property('lhs', 'rhs')
});
var multiplier = Multiplier.create();
multiplier.get('answer'); // => 42
multiplier.set('rhs', 3);
multiplier.get('answer'); // => 18
オブザーバ
他のメンバの値が更新された時に実行したい処理を記述できます。
値変更によって付随的に行う処理は、プロパティではなくオブザーバに処理を書くことが推奨されています。
var security = Ember.Object.create({
securityLevel: 5
});
security.addObserver('securityLevel', function() {
alert('セキュリティレベルが' + this.get('securityLevel') + 'に変わりました');
});
security.set('securityLevel', 3); // => オブザーバが実行され、alertポップアップが表示される。
以下の書き方でもOKです。
var security = Ember.Object.create({
securityLevel: 5,
securityLevelChange: function() {
alert('セキュリティレベルが' + this.get('securityLevel') + 'に変わりました');
}.observes('securityLevel')
});
バインディング
他のEmber.Objectインスタンスのメンバを参照する関連を定義します。
バインディングを使うには、ネームスペースとしてEmber.Applicationのインスタンスを作成する必要があるみたいです。
(普通にグローバル変数に入れたオブジェクトの値はバインディングできませんでした。)
バインディングの参照先の値が更新されると、バインディングの値も更新され、バインディングを参照しているプロパティ/オブザーバ/バインディングにも、値の更新が通知されます。
MyApp = Ember.Application.create();
MyApp.capital = Ember.Object.create({
name: "東京"
});
MyApp.country = Ember.Object.create({
capitalNameBinding: 'MyApp.capital.name'
});
// Later, after Ember has resolved bindings...
MyApp.capital.get('name'); // => "東京"
MyApp.country.get('capitalName'); // => "東京"
MyApp.country.set('capitalName', 'ネオサイタマ');
MyApp.capital.get('name'); // => "ネオサイタマ"
MyApp.country.get('capitalName'); // => "ネオサイタマ"
これら3つの機能を理解すれば、Ember.jsのデータバインディングの動作をすべて理解したことになります。