If you think about what Ember is actually doing to render that code, you can understand why it is slow. You’re creating 2k view instances, and rendering 2k templates. Templates that for the most part are doing very little. Especially if you don’t care about data binding.
For a first stab, let’s stop rendering through templates. This code uses itemViewClass
to render each item with a custom view instead of the view used internally by each
.
// Use with {{each item in items itemViewClass=App.SpanView}}
App.SpanView = Em.View.extend({
render: function(buffer) {
buffer.push("<span>"+this.get('content')+"</span>\n");
}
});
JSBin: http://jsbin.com/enapec/35/edit
With render
over-ridden, we need to interact with the render buffer ourselves.
Even faster would be getting rid of the view entirely. I think there are two ways to do this. You could create a custom view with a render
method that loops over all the items, and pushes each element onto the buffer. I think given the previous example you can get that going yourself.
Another simple option is to use a helper. A dumb helper like this is more difficult to wire up for re-rendering when the list changes, but sometimes it is the right solution.
// Use with {{eachInSpan items}}
Em.Handlebars.registerBoundHelper('eachInSpan', function (items) {
return (
new Handlebars.SafeString(
items.map(function (i) {
return '<span>'+i+'</span>';
})
)
);
});
Live JSBin: http://jsbin.com/enapec/34/edit
Lastly, you could do this in jQuery with didInsertElement
and the afterRender
queue. I don’t recommend it though.
Breaking it down.
I’m trying to do two things here, so please don’t jump down my throat on “this doesn’t address Angular vs Ember”. First and most of all, I’m trying to help find a real-world solution for @gunn’s problem. Because that is the important thing, and fixing those real-world problems help us build a better framework. So @gunn let me know if any of this is a good fit, and I’ll happily brainstorm some more options. Perf is fun stuff.
My second goal is to demonstrate that though Ember doesn’t magically just make everything always work fast, it does provide you with understandable and flexible tools. If we’re talking about performance, then we aren’t talking about normal anymore. You need to start thinking about what Ember is doing and what the browser is doing. The APIs for Ember internals are fantastic, and this is exactly the kind of time to use them.