简体   繁体   English

Emberjs Handlebars #each helper在绑定到计算属性时变慢

[英]Emberjs Handlebars #each helper slow when bound to computed properties

I'm running into a performance issue when I render a list of items using the #each helper or a collection view bound to some computed properties of an Ember.ArrayController. 当我使用#each帮助器或绑定到Ember.ArrayController的某些计算属性的集合视图渲染项目列表时,我遇到了性能问题。 Performance is fine with a small list of 10 - 20 items, but around 50 - 100 it starts to lag quite noticeably. 性能很好,有一个10-20项的小清单,但大约50-100,它开始明显滞后。 Try checking off a few todos or clicking "Add Todo" 尝试检查几个待办事项或点击“添加待办事项”

Example code is here: http://jsfiddle.net/Jonesy/ed3ZS/4/ 示例代码在这里: http//jsfiddle.net/Jonesy/ed3ZS/4/

I noticed that the childViews in the DOM get re-rendered with each change, which could very well be the intended behaviour at the moment, but I'd prefer to be able to just have a todo be removed from the DOM of unfinished todos list individually and appended to the bottom of the finished todos list, which would in theory be much less costly. 我注意到DOM中的childViews会随着每次更改而重新呈现,这很可能是目前的预期行为,但我更愿意能够从未完成的待办事项列表的DOM中删除待办事项。单独地并附加到完成的待办事项列表的底部,理论上这将更便宜。

What I'm hoping to have answered is whether am I looking at a performance issue with Ember collection views, or is displaying a list populated from a computed property a bad idea, and if so, will I need to manually manage the todo model's location in the view layer as it changes from unfinished to finished and vice versa. 我希望回答的是我是否在查看Ember集合视图的性能问题,或者显示从计算属性填充的列表是个坏主意,如果是这样,我是否需要手动管理todo模型的位置在视图层中,它从未完成变为完成,反之亦然。

This is a side-effect of how {{#each}} (and CollectionView , which is what powers it) works. 这是{{#each}} (和CollectionView ,它支持它的功能)如何工作的副作用。

Internally, CollectionView uses something called array observers . 在内部, CollectionView使用称为数组观察者的东西。 An array observer allows you to subscribe to mutations made to an array when they are done using Ember.Array 's mutation methods ( replace , pushObject , popObject , etc.) The API for array observers is described here . 使用Ember.Array的变异方法( replacepushObjectpopObject等),数组观察器允许您订阅对数组所做的突变。 此处描述了数组观察的API。

What this means is that, if you push a new object into a collection view, it will insert render one new element in the DOM and leave the rest in place. 这意味着,如果您将一个新对象推入一个集合视图,它将在DOM中插入一个新元素,并将其余元素保留在原位。

In the example you posted, however, the array is not being mutated--you're creating a brand new Array object every time a new item is added or removed. 但是,在您发布的示例中,数组未被变异 - 您每次添加或删除新项时都会创建一个全新的Array对象。 When the binding synchronizes, it replaces the old array with the new array. 绑定同步时,它会新数组替换旧数组。 To {{#each}} , this is no different than removing all of the elements and then adding them back in. {{#each}} ,这与删除所有元素然后重新添加它们没有什么不同。

The solution to the problem is to use a single array, instead of a computed property that returns a different array object each time it changes. 该问题的解决方案是使用单个数组,而不是每次更改时返回不同数组对象的计算属性。 You can see the Contacts app for an example of how to do this . 您可以在“联系人”应用中找到有关如何执行此操作的示例

Obviously this is a very common pattern, and we'd like to add some kind of filtering that does the right thing by default to Ember.ArrayController down the road. 显然这是一个非常常见的模式,我们想添加一些过滤,默认情况下做正确的事情就是Ember.ArrayController

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM