Em.Computed.sort触发计算属性两次

时间:2015-01-03 23:40:50

标签: ember.js

我的应用程序中的一个组件包含一个复制,过滤,排序,切片然后最终循环的数组。我遇到了Em.computed.sort()部分的问题,它似乎触发了另一个计算属性运行两次(这会在我的应用中引起一堆其他问题)。

{{#each item in final}}
    <li>{{item.name}} -- {{item.age}}</li>
{{/each}}

<button {{action "changeModel"}}>change model</button>

// initial property copied
initial: function(){
    return this.get('model').slice()
}.property('model'),

// sorted
sortProp: ['age:desc'],
sorted: Ember.computed.sort('initial', 'sortProp'),

// slice it and then loop through it - this function runs twice
final:  function(){
    return this.get('sorted').slice(0, 5)
}.property('sorted.[]'),

我的问题的简化版本是see my jsbin

基本上,当模型发生变化时,final()函数会运行两次 - 一次包含旧模型数据,第二次运行新的更新模型数据。在这两次期间,初始数据都是正确的,但Em.computed.sort仅在第二次final()运行时使用新的正确数据进行更新。

有没有办法避免两次调用final

2 个答案:

答案 0 :(得分:2)

我认为问题在于您不只是在model数组中添加/删除值,而是完全替换它。因此,或许Ember.computed.sort并不像您期望的那样适合您。

以下似乎有效

  sorted: function(){
    return this.get('initial').sortBy('age').reverse();    
  }.property('initial'),


  // slice it and then loop through it
  final: function(){
    console.log('FINAL ran', this.get('initial.length'), this.get('sorted.length'));

    return this.get('sorted').slice(0, 5)
  }.property('sorted'),

参见工作jsbin here

答案 1 :(得分:1)

请注意,Embers数组计算支持非常脆弱,且数量为issues

我的建议是不要使用它们,因为它们不太可能很快被修复,因为计算数组属性太复杂而无法在Ember中使用当前方法。

相反,只需使用常规属性,具体取决于'model。@ each.age',它会切割模型数组并返回一个新的排序数组。

如果你看一下Ember中的底层数组计算排序实现,你会发现我所描述的简单方法与Ember中令人畏惧的代码和状态跟踪相比,行为正确且有效。

如果您关心排序效率,那么我建议使用tsort实现,因为它通常是O(n)用于交互式更改,因为它利用了运行和部分排序的数组。