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

Em.Computed.sort triggers computed property twice

我的应用程序中的一个组件包含一个数组,该数组经过复制、过滤、排序、切片,最后循环遍历。我在 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 被调用两次?

我认为问题在于您不只是 model 数组的 adding/removing 值,而是完全替换它。因此,也许 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

请注意,Embers 数组计算支持非常脆弱,并且有许多 issues

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

而是使用常规 属性 取决于 'model.@each.age' 切片模型数组和 returns 一个新的排序数组。

如果您查看 Ember 中的底层数组计算排序实现,您会发现我描述的简单方法与 Ember.

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