In this section, we will look at the rendering process for SproutCore views. Updating the DOM is one of the slowest points in a web application and so, there are some very important steps that SproutCore uses to avoid touching the DOM unnecessarily. While all of the pre-built SproutCore views are already written to take full advantage of this, when we do custom rendering, it's important that we understand the render cycle in order to keep our views fast. Don't worry; it's not difficult to follow and you will have no problem creating complex views by the time we're done with this chapter.
We've already discussed how to affect the view's top level element by setting layerId
, tagName
, classNames
, and layout
but we haven't yet discussed how to create custom inner content for the element. To do so, there are two methods in SC.View
that we use: render
and update
. The render
method is called the first time the view is displayed and update
is called each time the view's display changes.
Let's look at the render
method first. Its job is to generate the HTML string to be passed to the Display layer and it does this using a simple HTML string builder called SC.RenderContext
. Let's start by creating a custom label view class, NameLabelView
, for our fictional application, MyApp
:
In my_app/views/name_label_view.js
:
MyApp.NameLabelView = SC.View.extend({ /** The name. */ name: '', /** @private Generates the view element's content. @param SC.RenderContext context the string builder object. */ render: function (context) { var name = this.get('name'), // Add a "Name:" label along with the name. context.push('<label class="name-label">Name: </label><span>' + name + '</span>'), } });
As you can see, to render this view, all we do is push a Name: label
term followed by the current value of name
into the render context we are given. The push
method simply adds the given string to the context, unaltered.
While you can use push
a lot of the time, the render context does have more declarative methods that we can use to build the output. Here is the same render
method using a series of build commands:
render: function (context) { var name = this.get('name'), // Add a "Name:" label. context = context.begin('label') .addClass('name-label') .push("Name: ") .end(); // Add the name. context = context.begin('span').push(name).end(); }
This time we used begin('label')
to start a new sub-context specific to the label element. We set its class using addClass
, pushed the Name:
string to it, and closed it off before starting another sub-context for span
.
Now, whenever an instance of MyApp.NameLabelView
is appended to the document, its render
function will be called and our custom label will appear in the DOM.
In order to update DOM most efficiently, when a pane is appended, SproutCore will call the render
function for every child view recursively, in order to build the entire HTML string at once. The final string will then be inserted into the DOM in a single call, which is significantly faster than building one child view at a time within the DOM.
3.12.123.189