Ember.js:设置一个值为嵌套对象的属性

时间:2015-09-22 17:59:03

标签: javascript ember.js

考虑以下Ember对象:

const FilterState = Ember.Object.extend({
  values: null,

  departmentChanged: Ember.observer('values.department_id', function() {
    // do something when the department changes
  }),
});

const filterState = FilterState.create({
  values: { department_id: 5, manager_id: 3 },
});

然后,在应用程序的某个时刻,我们希望将filterState值设置为一组新值。考虑以下三种替代方案来实现这一目标:

const newFilterValues = { department_id: 5 };

// This will unset the manager_id value, which is the desired behavior.
// However, it will trigger the departmentChanged observer,
// even though the department_id didn't actually change
filterState.set('values', newFilterValues);

// The following alternative won't trigger the observer, like intended
// but it won't unset the manager_id, which is necessary to happen
const filterValues = filterState.get('values');
Object.keys(newFilterValues).forEach(function(key) {
  filterValues.set(key, newFilterValues[key]);
});

// UPDATE:
// The following alternative is equivalent to the one just above,
// and therefore has the same shortcomings
filterState.
  get('values').
  setProperties(newFilterValues);

正如评论所强调的那样,第一个替代方案完成了工作,但它“错误地”触发了观察者,即使values.department_id属性没有真正改变。

第二种和第三种选择不会触发观察者,但两者都有一个更大的缺陷:新的过滤器值集中不存在的属性不会从{{1对象。

目前第一个是我可以使用的唯一选项,因为第二个替代方案的缺陷是不可接受的。但是,如果没有必要,观察者不应该开火。

我的替代方案是:

  1. 我可以尝试缓存先前的值,并在观察者内部手动检查值是否真的发生了变化,但这看起来过于冗长和蹩脚(这就是我目前正在做的事情)。
  2. Ember观察者机制是否有办法在观察者回调中传递旧值?
  3. 或者更好的是,它有一种方法可以实现仅在属性真正改变时才会触发的观察者? (或许有一些混合魔法?)
  4. 或者最后,还有其他方法可以设置filterState.values对象中的新值,其中观察者不会被触发,但是它也会按照预期的方式设置/取消设置所有内容吗? / LI>

1 个答案:

答案 0 :(得分:0)

values定义为Ember.Object:

filterState: FilterState.create({
  values: Ember.Object.create({ 
    department_id: 5, manager_id: 3
  })
})

然后它起作用,例如:

actions: {
  // will run observer only if department_id is changed
  changeDepartment: function(value) {
    var filterStateValues = this.get('filterState.values');
    filterStateValues.set('department_id', value);
  },
  // will not run observer
  changeOthers: function() {
    var filterStateValues = this.get('filterState.values');
    filterStateValues.setProperties({
      manager_id: 12
    });
  }
}

参见jsbin:http://emberjs.jsbin.com/widivemewe/edit?js,output