我始终认为.observes('someProperty')
和.property('someProperty')
的工作原理完全相同,只是前者用于触发函数调用,而后者用于保持对象属性为最新。
但现在我遇到了问题。我的控制器代码如下所示:
_logChange: function(){
console.log('model array observer fired');
}.observes('model.@each'),
statsData: function(){
console.log('statsData being updated');
...
return someArray;
}.property('model.@each')
观察者和计算属性都是监视模型。@但由于某种原因,观察者会在每次模型更改时触发,并且属性仅在神秘地死亡之前更新TWICE。 statsData
是在初始页面加载时计算一次,在第一次路径转换时计算一次,然后在此之后,没有任何转换(它们所做的基础model
中的更改)会影响它。
这里发生了什么?他们不应该以同样的方式回应变化吗?
请注意,我是在我的模板中使用statsData
属性。
答案 0 :(得分:2)
感谢Ember IRC的可爱人们,我能够弄明白。问题是我将statsData
传递给组件,如下所示:{{common-statistics values=statsData}}
在组件中,我有这个功能:
_validateValues: function(){
var values = this.get('values');
if(!values || !Ember.isArray(values) || values.length === 0)
{
this.set('values',[]);
}
}.on('willInsertElement')
正如您所看到的那样,设置values
,如果它不是组件所期望的那样。不幸的是,由于this JavaScript language feature,这也影响了控制器上的statsData
。通过在组件中设置statsData
,我打破了控制器上的计算属性。
所以Ember从来都不是问题。我只是没有意识到Ember对象上的对象属性与它们对“常规JavaScript对象”的行为方式相同。
答案 1 :(得分:1)
观察员立即开火,计算出火焰作为跑步循环的一部分,并以去抖动的方式安排。目前,您正在观看的是您在集合中添加或删除项目,而不是集合中其中一个项目的属性是否已更改。如果您想要观看特定属性,则需要指定它。
statsData: function(){
console.log('statsData being updated');
...
return someArray;
}.property('model.@each.cost')
如果您只想观看收藏品的更改,请使用[]
statsData: function(){
console.log('statsData being updated');
...
return someArray;
}.property('model.[]')