我的应用程序中的一个组件包含一个复制,过滤,排序,切片然后最终循环的数组。我遇到了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
?
答案 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)用于交互式更改,因为它利用了运行和部分排序的数组。