Rendering Views in Backbone.js isn't Always Simple
ianstormtaylor.com
ianstormtaylor.com
+------------------------------------+
| |
| MainView |
| |
| (content) |
| |
| |
|+----------++-----------++---------+|
|| || || ||
||SubView ||SubView ||SubView ||
|| || || ||
|| || || ||
|| || || ||
|| || || ||
|| || || ||
|| || || ||
|+----------++-----------++---------+|
+------------------------------------+
... and the data for the MainView is changing, while the data for the SubViews is not.So ideally, just re-render the top part of the MainView, and leave the SubViews alone. Instead of trying to reuse the same "render" function, imagine doing this instead:
mainModel.on("change", mainView.renderMainContent);
... where the hypothetical "renderMainContent" function just renders the template for the top half of the box. Or, maybe the top half of the box is a sub-view in its own right that can listen to its own events. Or, maybe you don't even need a template, and you can just update a couple of granular fields and/or attributes with jQuery. Whatever works.I usually start off by doing that because I'm lazy, then something usually bites me in the ass (usually - oh hey, we need a transition effect).
And the end result is a bunch of "sub rendering" methods that get called in render ... and as callbacks from model change events. (It's awfully nice when you have to load everything off the server - no default state in the DOM.)
I'd love to read an article about how you guys handle transitions though. We've implemented a few of them, but I have yet to work on them enough to have found really nice patterns.
Regardless, I'd still have the single `render` as a parent method that renders the initial template via `$.html()` so that my render helpers aren't appending their bits into the DOM. And that parent method still shouldn't break everything if it's called twice.
And then if you wanted to be safe, you could have the render helpers check to see if the view is `rendered` before attempting to do their bit. (And `return this.render();` instead if it isn't yet rendered.)
Trying to figure out how to cram everything into one function while still getting desired behaviour doesn't seem like the best way to go.
That being said, there are probably better ways to do it that don't involve Backbone, too.
IHMO, somehow better (but more verbose) approach is to consider view as a FSM. Each state may render view's complete representation (using the template), while each transform (an edge of view's Moore machine) may transform DOM tree as necessary (i.e. just update necessary elements instead of re-rendering a whole subtree, if possible).
I belive, this could be automated (as DOM is, essentially, a tree, differences between states could be found algorithmically), but haven't really tried it that way.
It would be nice to have the view re-drawn more intelligently so things don't need to be re-drawn and re-bound each time. But, I couldn't think of a generic way to do that without knowing the details of the view.
If anybody has any interest, the code I wrote is at http://phreeze.com