【问题标题】:Ember.js: Observing all object propertiesEmber.js:观察所有对象属性
【发布时间】:2012-12-14 04:29:07
【问题描述】:

我想观察对象属性的所有变化。
在以下示例中,如果名字或姓氏发生更改,我希望 personChanged 观察者通知我。
但是我想在所有对象属性上应用一些通用的东西(使用 Ember.keys() ??) 如何用更通用的东西替换“名字”、“姓氏”?

在我的例子中:

firstnamelastname 更改时调用personChanged

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

【问题讨论】:

标签: ember.js


【解决方案1】:

这可以使用ObjectProxy 两种风格,具体取决于您的要求。这两种方法的不同之处仅在于调用观察者的时间和次数,它们都依赖于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 时,会观察content 对象上已经 存在的所有属性,并且每次任何属性更改时都会调用函数personChanged。但是,由于观察者被急切地触发 [1],函数 personChanged 应该是 idempotent,而示例中的函数不是。下一个解决方案通过让观察者变得懒惰来解决这个问题。

解决方案 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');
    }
});

这里唯一的变化是实际的观察者函数现在只在the end of the Ember Run loop 调用,这可能是您正在寻找的行为。

其他说明

这些解决方案使用ObjectProxy,而不是在对象本身上定义观察者,以避免设置虚假观察者(在initwillDestroy 等属性上)或explicit list of properties to observe

此解决方案可以扩展为通过覆盖代理上的setUnknownProperty 来开始观察动态属性,以便在每次将键添加到content 时添加一个观察者。 willDestroy 将保持不变。

参考

[1] 感谢 Asyn Observers,这可能很快就会改变

【讨论】:

    【解决方案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/

    【讨论】:

    • Tx 但我的问题是获得一个通用的解决方案来观察所有对象属性(无需在观察方法中编写属性列表)
    • 抱歉,除非您将所有属性存储在一个数组或一个对象中并观察,然后进行一些手动计算以检索值,否则无法做到这一点。
    猜你喜欢
    • 2017-09-07
    • 2021-03-30
    • 2014-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    相关资源
    最近更新 更多