【问题标题】:Ember computed property not being updatedEmber 计算属性未更新
【发布时间】:2014-03-01 00:18:57
【问题描述】:

我不太完全确定为什么我的计算属性没有返回更新的值。

我有一个用户可以单击的选项列表,并且该操作会更新控制器的属性,即 Ember 对象。我有一个计算属性,它循环遍历该对象,查找该 Ember 对象属性具有非空值的键,如果找到,则返回 false,否则返回 true。

这里是东西:

App.SimpleSearch = Ember.Object.extend({
    init: function() {
        this._super();

        this.selectedOptions = Ember.Object.create({
            "Application" : null,
            "Installation" : null,
            "Certification" : null,
            "Recessed Mount" : null,
            "Width" : null,
            "Height" : null,
            "Heating" : null,
            "Power" : null
        });
    },

    selectedOptions: {},

    numOfOptions: 0,

    allOptionsSelected: function() {
        var selectedOptions = this.get('selectedOptions');
        for (var option in selectedOptions) {
            console.log(selectedOptions.hasOwnProperty(option));
            console.log(selectedOptions[option] === null);
            if (selectedOptions.hasOwnProperty(option)
                && selectedOptions[option] === null) return false;
        }
        return true;
    }.property('selectedOptions')
});


App.SimpleSearchRoute = Ember.Route.extend({
    model: function() {
        return App.SimpleSearch.create({
            'SimpleSearchOptions': App.SimpleSearchOptions,
            'numOfOptions': App.SimpleSearchOptions.length
        });
    },
    setupController: function(controller, model) {
        controller.set('model', model);
    }
});


App.SimpleSearchController = Ember.ObjectController.extend({
    getProductsResult: function() {
        var productsFromQuery;
        return productsFromQuery;
    },

    setSelection: function (option, selectionValue) {
        this.get('selectedOptions').set(option, selectionValue);
        this.notifyPropertyChange('allOptionsSelected');
    },

    actions: {
        registerSelection: function(option) {
            console.log('registering selection');
            console.log(this.get('allOptionsSelected'));
            console.log(this.get('selectedOptions'));
            this.setSelection(option.qname, option.value);
        },

控制器中的动作registerSelection 触发得很好,但我只看到SimpleSearch 模型中的console.log 一次。一旦第一次计算了属性,之后就不再关注它,这意味着每当调用它时,计算的属性都不会观察到 selectedOptions 的变化:

setSelection: function (option, selectionValue) {
    this.get('selectedOptions').set(option, selectionValue);
    this.notifyPropertyChange('allOptionsSelected');
},

编辑:

实际上我没有改变任何东西就解决了我的问题。

我更改了以下行:

this.notifyPropertyChange('allOptionsSelected');

到:

this.get('model').notifyPropertyChange('selectedOptions');

notifyPropertyChange 需要在模型(或具有特定属性的观察者的 Ember 对象)的上下文中调用,作为参数发送的字符串是更新的属性的名称。

在我进行更改后,它按预期工作。

【问题讨论】:

    标签: javascript ember.js


    【解决方案1】:

    Ember 不会观察对象上的任何变化,它会观察单个属性。

    这对您有何影响?好吧,在这种方法中,您正在观看selectedOptions,但该对象本身仍然是同一个对象,您可能正在更改它的属性,而不是对象本身。然后你告诉控制器范围内的 Ember allOptionsSelected 已经改变,所以它重新抓取它,但它没有重新计算它,因为它不是脏的,它只是改变了。您真的想说selectedOptions 已更改为让allOptionsSelected 重新计算其值。不幸的是,您是在控制器范围内执行此操作的,因此告诉控制器属性已更改无关紧要。

    allOptionsSelected: function() {
      var selectedOptions = this.get('selectedOptions');
      for (var option in selectedOptions) {
         console.log(selectedOptions.hasOwnProperty(option));
         console.log(selectedOptions[option] === null);
         if (selectedOptions.hasOwnProperty(option)
            && selectedOptions[option] === null) return false;
         }
      return true;
    }.property('selectedOptions')
    

    这是一个虚拟示例,显示了导致它实际更新的原因。

    http://emberjs.jsbin.com/iCoRUqoB/1/edit

    老实说,由于您没有查看特定属性,因此我可能会创建一个数组,或者在处理添加/删除/修改属性的对象上创建一个方法,以便您可以在其范围内触发属性更改,更新所有父级监听器的变化。

    【讨论】:

    • 谢谢 - 我真的 只是 在回来检查问题之前想通了 - 我更改了 .propert('selectedOptions') to .property('selectedOptions.Application', 'selectedOptions .Installation','selectedOptions.Certification'...`,然后它正在监视各个子属性。这些选项基于返回的一些 JSON,所以我认为您只使用数组是正确的。我m 无论如何设置选项的长度或数量,所以我将设置一个条件来检查。
    【解决方案2】:

    Ember 计算属性依赖键可以是一个

    1. 属性键。 例如:'jobTitle'
    2. 计算的属性键。 例如:“公司名称”
    3. 对象的属性键。 例如: 'salesAccount.name 和 salesAccount.website'

    从 Ember.model 定义中提取的示例:

    ...
       jobTitle : DS.attr('string'),
       salesAccount: belongsTo('salesAccount'),
    
       companyName: Ember.computed('jobTitle', 'salesAccount.name', {
        get: function () {
          return this.get('salesAccount.name');
        }
      }),
    
      companyWebsite: Ember.computed('salesAccount.website', 'companyName',  {
        get: function () {
          return this.get('salesAccount.website');
        }
      })
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-04
      • 2017-04-10
      • 2014-08-19
      • 1970-01-01
      • 1970-01-01
      • 2019-04-18
      • 2016-04-22
      相关资源
      最近更新 更多