You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To render content to the screen, you need a component. For the most part, components are just objects that respond to render with a virtual-DOM node. The easiest way to generate these is by including the Clearwater::Component mixin.
The render method calls div with some text. When this component is rendered into your document, it will be the same as if you'd rendered this HTML: <div>Hello, world!</div>.
In order to render a component, you need an application object with an instance of this component:
Once you have that, you simply invoke the app with call. When your application's state changes, you simply use the render method to update the UI to match. If, for example, your app displays the current time, this means the current time is part of your application state, so you may want to update it every second or every minute:
classClockincludeClearwater::Componentdefrenderdiv(Time.now.strftime('%I:%M:%S%P'))# "3:53:12pm"endendapp=Clearwater::Application.new(component: Clock.new)app.call# Re-render every secondBowser.window.interval(1){app.render}
Complex contents
In these examples, the only content inside of our elements was a single string. In real apps, you'll never have just one element with one string, but instead one container element with many child elements that may also have their own child elements.
Child elements are as easy as replacing the string with another element:
div(span('Hello, world'))
This places a span element within the div. If you want to supply multiple child elements, you can also pass an array:
div([span('Hello, '),span('World!'),])
You can also replace some of these method calls with other component instances:
classGreetingincludeClearwater::Componentdefrenderdiv([Hello.new('World')])endend# Using a Struct to remove boilerplate of constructor and attr_readerHello=Struct.new(:name)dodefrenderspan("Hello, #{name}!")endend
Rendering lifecycle
The lifecycle is rarely necessary to keep in mind, but in case you need to track down a bug, it can be helpful. A render occurs like this:
Call app.render
App delays the render until the end of the current animation frame (or until the next if currently in an animation-frame callback) to coalesce further render calls
Rendering begins
VDOM generation begins
HTML tag methods return VDOM nodes directly
If a render-able object is encountered during VDOM generation …
If it is a CachedRender component, it gets wrapped in a delayed render
Otherwise, its render method is called and its return value replaces it in the VDOM tree
VDOM reconciliation begins
Typical VDOM diff and patching occurs for VDOM nodes
New DOM nodes are created based on the corresponding VDOM nodes for any VDOM nodes that were not in the previous render
Existing VDOM nodes have their corresponding DOM nodes updated (recursively) to match their structure
DOM nodes whose VDOM nodes have been removed are also removed from the DOM
If a CachedRender delayed render is encountered, its should_render? method is invoked with the previous instance of itself
If it returns a truthy value, a new VDOM node will be generated from the component's render method and the diff/patch process will go down that tree
If it returns false or nil, that DOM subtree will not be touched
Browser recalculates styles
Browser recalculates layouts for DOM subtrees whose dimensions changed based on those styles
Browser paints the updated DOM to the screen
The text was updated successfully, but these errors were encountered:
To render content to the screen, you need a component. For the most part, components are just objects that respond to
render
with a virtual-DOM node. The easiest way to generate these is by including theClearwater::Component
mixin.The
render
method callsdiv
with some text. When this component is rendered into your document, it will be the same as if you'd rendered this HTML:<div>Hello, world!</div>
.In order to render a component, you need an application object with an instance of this component:
Once you have that, you simply invoke the app with
call
. When your application's state changes, you simply use therender
method to update the UI to match. If, for example, your app displays the current time, this means the current time is part of your application state, so you may want to update it every second or every minute:Complex contents
In these examples, the only content inside of our elements was a single string. In real apps, you'll never have just one element with one string, but instead one container element with many child elements that may also have their own child elements.
Child elements are as easy as replacing the string with another element:
This places a
span
element within thediv
. If you want to supply multiple child elements, you can also pass an array:You can also replace some of these method calls with other component instances:
Rendering lifecycle
The lifecycle is rarely necessary to keep in mind, but in case you need to track down a bug, it can be helpful. A render occurs like this:
app.render
render
-able object is encountered during VDOM generation …CachedRender
component, it gets wrapped in a delayed renderrender
method is called and its return value replaces it in the VDOM treeCachedRender
delayed render is encountered, itsshould_render?
method is invoked with the previous instance of itselfrender
method and the diff/patch process will go down that treefalse
ornil
, that DOM subtree will not be touchedThe text was updated successfully, but these errors were encountered: