Using document fragment when rendering a backbone view

October 27th, 2011 § 1 comment § permalink

Backbone.js is pretty fun to use. Right out of the box it makes app development quick and organized. Fully grokking how to adapt to using view controllers is a bit of a change and the event system is happily powerful, yet blending it with jQuery events doesn’t seem immediately obvious. All the same it does a great job of giving great tools for organization and structure while staying out of your way.

One drawback to using a library that does magic is that if you’re not careful you can miss some important details. In this case I’m talking about injecting your views into the DOM. Blindly following the create view/render into element pattern as described in the documentation is usually fine. However, if you are using a view to render a list of children the $(this.el).append(view.render().el) quickly becomes costly.

For my needs I wanted to add an arbitrarily-long list of elements to an ordered list. Instead of blindly looping over models, creating views and shoving them into the list one at a time I decided to add all rendered views into a document fragment in memory and then append that fragment on to my list. Clean code for rendering, only one DOM adjustment for speed.

Example Code!

var containerView = Backbone.View.extend({
//... snip
	render: function() {
		var template = _.template($('#regular_ol_template').html()),
			self = this;

		$(self.el).html(template(self.model.toJSON()));

		self.list = $('.list', self.el);

		var frag = document.createDocumentFragment();
		_.each(self.model.things.models, function(thing) {
			frag.appendChild(self.createThing.call(this, question).render().el);
		});
		self.list.append(frag);

		return self;
	},

	createThing: function(thing) {
		return new ThingView({model:thing});
	}
//... snip
});

But why make a separate function?

What you’re not seeing is another method named addThing which uses createThing and does more work – to my model, spinning up other views, etcetera. It’s also good not to bind the creation of elements solely into your render method. You want to be able to add more things to your list without fully re-rendering it. That way, should someone else decide to use my model or view in the app, elements in the list can be adjusted without the performance overhead of creating the whole list again.

Result

There you have it! You have now rendered your Backbone.js views into memory and appended them to the DOM in one fell swoop. Instead of abusing the DOM in your loop cycle you’ve speedily created them in memory. Isn’t that much kinder to the DOM? The answer is yes, yes it is.

What do you think? How would you change this? Comments!