【问题标题】:How can an observer find out the before and after values of the observed property in Ember.js?观察者如何找出 Ember.js 中被观察属性的前后值?
【发布时间】:2023-03-16 02:43:01
【问题描述】:

请查看 ud3323 提供的另一个问题的解决方案:http://jsfiddle.net/ud3323/ykL69/。此解决方案使用红色突出显示更改的值。我还有一个额外的要求:如果该值增加了绿色高光,如果它减少了红色高光。为此,我需要了解观察者的旧值和新值。有没有办法做到这一点?

附: Embers 文档没有说明观察者函数中可用的内容。从这个例子我可以看出,由于观察者是在 itemRowView 中定义的,“this”指向 itemRowView。

【问题讨论】:

    标签: ember.js


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

    看看beforeObservers。 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 看起来可以达到相同的结果。
    • View state 是一个内部属性,不应直接从您的任何代码中引用。此外,您可以使用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 名称无关紧要。但是,是的,约定是对类使用大写字母,对实例使用小写字母。
    猜你喜欢
    • 2013-07-04
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 2015-05-11
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多