template vs render()
This mental model attempts to reduce the cognitive complexity of authoring components:
- The
templateis a read-only property (initialized with agetkeyword) that represents how the component view is rendered. - There is a
render()method that triggers a view render. - This
render()method is automatically called under the hood every time an attribute value changed. - You can optionally call this
render()method at any point to trigger a render if you need (eg, if you have private unobserved properties that need to manually trigger a render) - Overriding the
render()function for handling a customtemplateis also possible. Here’s an example of usinglit-html: View on CodePen ↗
See it live: Templating demo ↗ for the two template kinds, and Render reconciliation demo ↗ for what an in-place re-render preserves: focus, caret position and an uncommitted input value all survive.
Composing components
Section titled “Composing components”A component’s template can contain other components, nested as deep as you like:
class CounterBoard extends WebComponent { static props = { title: 'Board' } get template() { return html` <h3>${this.props.title}</h3> <counter-row name="alpha"></counter-row> <counter-row name="bravo"></counter-row> ` }}Each nested component owns the DOM it renders for itself. When an outer component re-renders, the reconciler patches the props it passes down to a nested element (that is how data flows from parent to child) but never touches the element’s own children, so a nested component keeps its rendered content and any internal state even when an ancestor re-renders for an unrelated reason. Data flows down as attributes, so pass values a nested component can read back from an attribute: primitives, or objects/arrays that survive a JSON round-trip. See it live: Nested composition demo ↗.
The one exception is slot projection: children you write inside a
shadow-DOM component’s tag are your content, projected into its <slot>, so the
parent keeps reconciling those. A light-DOM component, by contrast, renders over
its own children, so pass data to it through attributes rather than as projected
children.