30
loading...
This website collects cookies to deliver better user experience
Counter
component example, and how state serialization works. (Note that this is the output of the server-side rendered HTML, not necessarily specific code developers would be hand-coding.)<div ::app-state="./AppState"
app-state:1234="{count: 321}">
<div decl:template="./Counter_template"
on:q-render="./Counter_template"
::.="{countStep: 5}"
bind:app-state="state:1234">
<button on:click="./MyComponent_increment">+5</button>
321.
<button on:click="./MyComponent_decrrement">-5</button>
</div>
</div>
::app-state
(application state code): Points to a URL where the application state mutation code can be downloaded. The state update code is only downloaded if a state needs to be mutated.app-state:1234
(application state instance): A pointer to a specific application instance. By serializing the state, the application can resume where it left off, rather than replaying the rebuilding of the state.decl:template
(declare template): Points to a URL where the component template can be downloaded. The component template is not downloaded until Qwik determines that the component's state has changed, and needs to be rerendered. on:q-render
(component is scheduled for rendering): Frameworks need to keep track of which components need to be rerendered. This is usually done by storing an internal list of invalidated components. With Qwik, the list of invalidated components is stored in the DOM in the form of attributes. The components are then waiting for the q-render
event to broadcast. ::.="{countStep: 5}"
(Internal state of component instance): A component may need to keep its internal state after rehydration. It can keep the state in the DOM. When the component is rehydrated it has all of the state it needs to continue. It does not need to rebuild its state.bind:app-state="state:1234"
(a reference to shared application state): This allows multiple components to refer to the same shared application state. markDirty()
), or because a component is invalidated implicitly because the application shared state has changed. count
is kept in the application state under the key app-state:1234
. If the state is updated it is necessary to invalidate (queue for rerender) the components that depend on that application state. How should the framework know which components to update?count
gets updated, Qwik can internally determine which components need to be invalidated by executing this querySelectorAll
.querySelectorAll('bind\\:app-state\\:1234').forEach(markDirty);
markDirty()
on it. markDirty()
invalidates the component and adds it to a queue of components which need to be rerendered. This is done to coalesce multiple markDirity
invocations into a single rendering pass. The rendering pass is scheduled using requestAnimationFrame
. But, unlike most frameworks, Qwik keeps this queue in the DOM in the form of the attribute as well.<div on:q-render="./Counter_template" ... >
requestAnimationFrame
is used to schedule rendering. Logically, this means that requestAnimationFrame
broadcasts the q-render
event which the component is waiting on. Again querySelectorAll
comes to the rescue.querySelectorAll('on\\:q-render').forEach(jsxRender);
querySelectorAll
can be used to identify all the components which should receive the event broadcast. jsxRender
function is then used to rerender the UI. q-render
event is broadcast to determine if the component needs to be rendered, it is easy to determine if the component is visible and simply skip the rendering for that component. Skipping the rendering also means that no template, or any other code, is required to be downloaded.innerHTML
it at the end of the DOM. Because Qwik is stateless, the additional HTML can be just inserted without causing any issues to the already running application. Qwik does not know about the new HTML until someone interacts with it, and only then it gets lazy hydrated. The use case described above is very difficult to do with the current generation of frameworks.