0

具有基于相同依赖项的 2 个计算属性仅运行一个计算属性。文档说,当我想要以下情况时,它被缓存了怎么办:

  foo: (->
    console.log 'foo'
  ).property('dependency')

  bar: (->
    console.log 'bar'
  ).property('dependency')

现在bar没有调用,我不得不求助于观察者。我可以让它工作吗?


编辑

问题是关于计算属性的,但它没有反映在示例代码中 - 而不是property我使用的observes. 现在已更改。很抱歉造成混乱。


编辑#2

我修改了@MilkyWayJoe 的出色示例,使其现在看起来像我的解决方案。不幸的是(或幸运的是)它有效,但我的解决方案没有。这是我所追求的要点:

在滑块的帮助下,我可以设置要转移到另一个信用卡提供商的余额值。假设值为transferValue。每当它发生变化时,我都必须计算加上转会费的年利息。

例如,假设我目前的信用卡中有 1000 美元,年利率为 19%。这太多了,所以我寻找另一种更便宜的解决方案。事实证明,银行 X 提供余额转账信用卡 Y,利率为 10% + 3.5% 转账费。

好的。所以我在滑块上设置了 1000 美元,这就是魔法。我想在价值发生变化时计算利率和转账费用。

在修改后的示例中它可以工作:http: //jsfiddle.net/gqSMU/2/ 但在我的第一个解决方案中没有这样做。有点像这样:

cardInterest: (->
    apr = @get 'purchaseRate'
    amount = @get 'transferValue'
    @get('calculatedTransferFee') + @calculateInterest apr, amount
  ).property('transferValue', 'calculatedTransferFee')

如您所见,它访问calculatedTransferFee. 问题是没有重新计算该值。我不确定是否值得一提,但在第一个解决方案cardInterest中,Handlebars 模板仅要求。

这是我目前与观察者的解决方案:

calculatedTransferFee: 0
  transferValueDidChange: (->
    if @get('isCurrentCardChosen')
      transferFee = parseFloat @get('balanceTransferRate') / 100
      transferValue = @get 'transferValue'
      calculatedTransferFee = if isNaN(transferFee) then 0 else transferFee * transferValue
      @set 'calculatedTransferFee', calculatedTransferFee
  ).observes('transferValue')

这不是一个很好的解决方案,是吗?这就是为什么我认为这可能是比求助于观察者更好的解决方案。

我希望现在它更清楚了。如果有任何进一步的反馈,我将不胜感激!

4

1 回答 1

0

不太确定我是否理解您要实现的目标,因为您正在谈论property但您的代码正在使用observes(我意识到这是一个概念性示例代码,只是不确定您要去哪里)。

通常,property它将是一个值的“反应式访问器”,并且 99.9% 的时间您希望它被缓存(默认情况下,除非您说.property('whatever').volatile()),而observe当它正在观察的任何属性发生变化时将触发一个函数。如果您只想为相同的依赖项触发两个属性,您可以:

App.SomeModel = Em.Object.extend({
    someDependency: true,
    foo: function() {
        // all that's in here will fire only once when 'dependency' changes, and store
        // the returning value in cache, and every time something reads this property, 
        // it will retrieve the cached value. 
        // A way to test this, is to run the following from your View: 
        // "alert(this.controller.get('content.foo'));"
        // It will alert the string but will not log "whatever bro" again. 
        console.log('whatever bro'); 
        return "this.foo %@ a dependency".fmt(this.get('someDependency') ? "has" : "doesn't have");
    }.property('someDependency'),
    bar: function() {
        // same as above
        console.log('whatever dude'); 
        return "this.bar %@ a dependency".fmt(this.get('someDependency') ? "has" : "doesn't have");

    }.property('someDependency'),
    nope: function() {
        // same as above, except this is volatile 
        // and will fire the console.log every time
        console.log('y\'all need science'); 
        return "this.nope %@ a dependency".fmt(this.get('someDependency') ? "has" : "doesn't have");

    }.property('someDependency').volatile() 
});

(见小提琴

如果您需要每次都记录它(可能出于调试或任何原因),您可以使用volatileor observes

如果我绊倒了而这不是您想要的,也许您可​​以改写您的问题或将示例代码刷新为更接近您的现实生活场景的内容,以澄清所问的内容。

于 2013-08-29T20:58:13.243 回答