Backbone.js Tip – Top-Down Rendering

JavaScript 5 5 Comments

For rendering performance reasons (avoiding reflows), it’s common to render child views before parent views (bottom-up rendering). If your app doesn’t need flash elements (i.e., fallback for audio or video), you should consider bottom-up rendering. In the exceptional case where you still need a video here or there, you can use a promise or callback to trigger the multimedia element rendering after the page is done. Thanks to Joe Zim for reminding me of this. I’ve been making audio/video-intensive apps for the last couple of years.

Top-Down Rendering is a solution to a common problem that crops up when rendering
views with lots of multimedia content. Some elements (e.g. flash and object embeds) can’t be manipulated safely cross browser unless they are rendered (and sometimes visible). This is particularly problematic for apps which deal with rich multimedia content, such as audio or video.

Unfortunately, it’s common to see examples of view rendering where a child view will render elements into a detached DOM element, and then expose that element for the parent view to render. For example, in the parent view’s .render() method, you might see something like this:

The problem here is that the parent’s element has not yet been rendered and attached to the DOM before the itemView’s .render() method is called. If the child view needs to render video and fall back to flash for an older version of IE, for example, this will fail.

It’s common to nest views a few levels deep, so once you start down the path of bottom-up rendering, it becomes a pain to fix. Luckily, the solution is simple. Just reverse the order of the rendering steps. Assuming that top-down rendering has been applied throughout the code, the parent view’s element should already be rendered before its .render() method is ever called, so this is safe:

  1. I agree that the top-down approach can help with certain cases such as video, but overall, it’s best to render the subviews first because then when you render the parent, the browser only has to paint the screen once. This is a common pattern for performance.

    • Eric Elliott - February 8, 2013

      Very good point, Joe. Thanks for your comment!

    • Eric Elliott - February 8, 2013

      Sometimes it isn’t always so cut and dry, though. For instance, if you need to render a large collection of items, you might not want to wait for all of those items to load and render before you start to draw the list. In that case, a top-down approach, where each item appends itself to the parent view as soon as its ready might provide a snappier user experience. What you need to watch out for are reflows — where the page needs to rerender itself in order to accommodate the size of new elements being rendered to the screen. If each item is of uniform size, and it’s being appended to a list, it should be able to draw without triggering a reflow. In that case, you might want to render top-down.

      • Try, but if you’re loading the collection asynchronously, as you seem to be saying, then the outside view would be rendered on the page before the asynchronous data has finished loading anyway. Asynchronous operations tend to create a lot of exceptions to rules because they can be handled in so many ways.

        • Eric Elliott - April 14, 2014

          If you know the size of the collection, and the size of each item in the collection, then you can set the size of the collection container in advance, and asynchronously loaded items won’t trigger a reflow.

Add Comment Register

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">