观察者如何找出 Ember.js 中被观察属性的前后值?
Posted
技术标签:
【中文标题】观察者如何找出 Ember.js 中被观察属性的前后值?【英文标题】:How can an observer find out the before and after values of the observed property in Ember.js? 【发布时间】:2012-03-03 08:03:11 【问题描述】:请查看 ud3323 提供的另一个问题的解决方案:http://jsfiddle.net/ud3323/ykL69/。此解决方案使用红色突出显示更改的值。我还有一个额外的要求:如果该值增加了绿色高光,如果它减少了红色高光。为此,我需要了解观察者的旧值和新值。有没有办法做到这一点?
附: Embers 文档没有说明观察者函数中可用的内容。从这个例子我可以看出,由于观察者是在 itemRowView 中定义的,“this”指向 itemRowView。
【问题讨论】:
【参考方案1】:我使用计算属性路由到模型的属性并将最后一个值存储在其集合中。
registrationGroup: Em.computed('regionModel.registrationGroup',
get:->
@.get('regionModel.registrationGroup')
set:(key, value, oldValue)->
@.set('lastRegistrationGroup', oldValue)
@.set('regionModel.registrationGroup', value)
)
【讨论】:
CoffeeScript 中@
之后不需要一个点。例如。 @get()
.
另外,你为什么使用吸气剂?您是否在防止重写?
我在 CS 中使用点是因为我发现在其中搜索某些调用更容易,而且我还发现它提高了可读性。 Getter 只是为了保持一致性,所以我可以使用相同的属性来获取和设置。【参考方案2】:
beforeObserver
在 Ember 1.10 中一直是 deprecated。
改为使用手动缓存:
doSomething: Ember.observer( 'foo', function()
var foo = this.get('foo');
var oldFoo = this.get('_oldFoo');
if (foo === oldFoo) return;
// Do stuff here
this.set('_oldFoo', foo);
)
【讨论】:
当这个观察者没有它订阅的任何属性时,它如何知道何时被解雇?我用 .observes('foo') 尝试了类似的东西,并且 foo 值已经在观察者函数中改变了。 谢谢,我已经用依赖键更新了我的答案。是的,从属值在观察者中是新的。您将其与之前的值进行比较,如果它不同于您知道的值已更改。 好的,我明白了,感谢您的澄清和更新。就我而言,如果新值未定义,我实际上是在使用旧值来设置新值,因此最好使用 setter,因为这样我就不需要存储该值。但我认为这在很多情况下都很有效。【参考方案3】:看看beforeObserver
s。 beforeObserver
在属性更改之前触发。因此,如果您在 beforeObserver 中 get
属性,您将拥有更改前的值。您可以使用Ember.addBeforeObserver
或通过observesBefore
函数原型扩展来设置这种类型的观察者。
这将为您提供实现目标所需的一切。我根据您的小提琴创建了以下 JSBin 以在此处进行演示:http://emberjs.jsbin.com/qewudu/2/edit
于 2014 年 10 月 7 日更新以反映 Ember 1.7.x 中的行为。
2015 年 2 月更新:beforeObserver
已被弃用。查看此问题的其他答案。
【讨论】:
Ember.addBeforeObserver 更干净。谢谢卢克! 顺便说一句,我最近注意到函数上有一个observesBefore
扩展,所以代码可以像jsfiddle.net/ye3M2 那样做得更好
我不相信提供的“价值”。我正在测试版本 1.5.1
1.7.0 版中也没有值参数。此解决方案已弃用。【参考方案4】:
使用willInsertElement
存储初始值,当值改变时,比较两者:
Quotes.itemRowView = Ember.View.extend(
tagName: 'tr',
initialValue: null,
willInsertElement: function()
var value = this.get('content').value;
this.set('initialValue', value);
,
valueDidChange: function()
// only run if updating a value already in the DOM
if(this.get('state') === 'inDOM')
var new_value = this.get('content').value;
// decreased or increased?
var color = (new_value > this.get('initialValue') ) ?
'green' : 'red' ;
// store the new value
this.set('initialValue', new_value);
// only update the value element color
Ember.$(this.get('element')).find('.quote-value').css('color', color);
.observes('content.value')
);
看看jsfiddle http://jsfiddle.net/ykL69/15/
【讨论】:
谢谢扎克。这很好用。但是,如果我的理解是正确的,则此代码中存在一个错误。似乎 willInsertElement() 只被调用一次(最初插入元素时)。因此,为了保持颜色正确出现,在 valueDidChange() 结束时,您必须将 initialValue 重新初始化为新值 - 从而确保将下一个更改与该值进行比较。虽然这种方法总体上有效,但视图现在正在成为缓冲值的地方。相反,如果观察者可以提供旧值和新值,代码会简单得多。 更正了我的回答。正如@Luke 所说,beforeObserver 看起来可以达到相同的结果。 Viewstate
是一个内部属性,不应直接从您的任何代码中引用。此外,您可以使用this.$('.quote-value')
,而不是使用Ember.$(this.get('element')).find('.quote-value)
。
请注意:“Quotes.itemRowView”不应该是“Quotes.ItemRowView”,因为它是扩展而不是从 Ember.View 创建的? emberist.com/2012/04/09/naming-conventions.html
@iX3 名称无关紧要。但是,是的,约定是对类使用大写字母,对实例使用小写字母。以上是关于观察者如何找出 Ember.js 中被观察属性的前后值?的主要内容,如果未能解决你的问题,请参考以下文章