9

オブジェクトのプロパティのすべての変更を観察したいと思います。
次の例では、名または姓が変更された場合に、personChangedオブザーバーから通知を受け取りたいと思います。
しかし、すべてのオブジェクトプロパティに一般的なものを適用したいと思います(Ember.keys()??を使用)。「firstname」、「lastname」をより一般的なものに置き換える方法は?

私の例では:

personChangedfirstnameまたはlastnameが変更されたときに呼び出されます。

 App.MyObject: Ember.Object.create({
   firstname: 'first',
   lastname: 'last',
   personChanged: Ember.observer(function() {
            console.log("person changed");
   }, 'firstname', 'lastname') 
 })
4

2 に答える 2

8

これはObjectProxy、要件に応じて、2つのフレーバーを使用して可能です。どちらのアプローチも、オブザーバーが呼び出されるタイミングと回数だけが異なり、どちらもに依存していEmber.keysます。

両方のソリューションのHTMLは同じです。

HTML

<script type="text/x-handlebars" data-template-name="app">
    Name: {{App.MyObject.firstname}} {{App.MyObject.lastname}}

    <ul>
    {{#each App.List}}
        <li>{{this}}</li>
    {{/each}}
    </ul>
</script>

解決策1

JsFiddle: http: //jsfiddle.net/2zxSq/

Javascript

App = Em.Application.create();

App.List = [];

App.MyObject = Em.ObjectProxy.create({
    // Your Original object, must be defined before 'init' is called, however.
    content: Em.Object.create({
        firstname: 'first',
        lastname:  'last'
    }),


    // These following two functions can be abstracted out to a Mixin
    init: function () {
        var self = this;
        Em.keys(this.get('content')).forEach(function (k) {
            Em.addObserver(self.get('content'), k, self, 'personChanged')
        });
    },

    // Manually removing the observers is necessary.
    willDestroy: function () {
        var self = this;
        Em.keys(this.get('content')).forEach(function (k) {
            Em.removeObserver(self.get('content'), k, self, 'personChanged');
        });
    },

    // The counter is for illustrative purpose only
    counter: 0,
    // This is the function which is called.
    personChanged: function () {
        // This function MUST be idempotent.
        this.incrementProperty('counter');
        App.List.pushObject(this.get('counter'));
        console.log('person changed');
    }
});

App.ApplicationView = Em.View.extend({
    templateName: 'app'
});

// Test driving the implementation.
App.MyObject.set('firstname', 'second');
App.MyObject.set('lastname',  'last-but-one');

App.MyObject.setProperties({
    'firstname': 'third',
    'lastname' : 'last-but-two'
});

初期化中、オブジェクトにすでに存在するMyObjectすべてのプロパティが監視され、プロパティが変更されるたびに関数が呼び出されます。ただし、オブザーバーは熱心に解雇されるため[1]、関数はべきである必要がありますが、この例の関数はそうではありません。次の解決策は、オブザーバーを怠惰にすることでこれを修正します。contentpersonChangedpersonChanged

解決策2

JsFiddle: http: //jsfiddle.net/2zxSq/1/

Javascript

App.MyObject = Em.ObjectProxy.create({
    content: Em.Object.create({
        firstname: 'first',
        lastname:  'last'
    }),


    init: function () {
        var self = this;
        Em.keys(this.get('content')).forEach(function (k) {
            Em.addObserver(self, k, self, 'personChanged')
        });
    },

    willDestroy: function () {
        var self = this;
        Em.keys(this.get('content')).forEach(function (k) {
            Em.removeObserver(self, k, self, 'personChanged');
        });
    },

    // Changes from here 
    counter: 0,
    _personChanged: function () {
        this.incrementProperty('counter');
        App.List.pushObject(this.get('counter'));
        console.log('person changed');
    },

    // The Actual function is called via Em.run.once
    personChanged: function () {
        Em.run.once(this, '_personChanged');
    }
});

ここでの唯一の変更は、実際のオブザーバー関数がEmber Runループの最後でのみ呼び出されるようになったことです。これは、探している動作である可能性があります。

その他の注意事項

これらのソリューションはObjectProxy、オブジェクト自体にオブザーバーを定義する代わりに、スプリアスオブザーバー(、などのプロパティ)または監視するプロパティの明示的なリストを設定しないようにするためにinit使用willDestroyます

setUnknownPropertyこのソリューションは、キーがに追加されるたびにオブザーバーを追加するためにプロキシでをオーバーライドすることにより、動的プロパティの監視を開始するように拡張できますcontent。はwillDestroy同じままになります。

参照

[1]AsynObserversのおかげでこれはすぐに変更される可能性があります

于 2012-12-29T18:26:47.597 に答える
2

インラインオブザーバーを使用するのは正しいですが、構文エラーがいくつかあります。ただし、キーワードを使用する方がさらに簡単ですobserves。だから私はあなたの例を少し下に微調整しました。

App.MyObject: Ember.Object.create({
    firstname: 'first',
    lastname: 'last',
    personChanged: function() {
        //firstname or lastname changed
    }.observes('firstname','lastname')
});

注:プロパティを引用符で囲みます

ソース: http ://emberjs.com/guides/object-model/observers/

于 2012-12-29T07:33:56.807 に答える