define
Registers a name usable in expressions of every scope. It is a tool, not state. It cannot override runtime names ($scope and so on).
plugin() is the one way to add anything to the runtime. An extension is a plugin too, and the built-in ones are made the same way.
An extension is a single plugin function. It uses the tools it receives to register names, attributes, components, and values to provide. Below is an extension that adds one price-formatting helper and one attribute.
A plugin function receives the tools below. Called before start, it is queued and runs at start. Called after start, it runs right away.
Registers a name usable in expressions of every scope. It is a tool, not state. It cannot override runtime names ($scope and so on).
Registers a name created for each h-scope. When read, it receives that scope's handle (host.el) and builds the value. Use it for tools that depend on the scope element, and call it before start. Names created per scope →
Creates a new attribute. directive('focus', …) becomes h-focus. The function it returns is called on cleanup.
Creates a new tag. It takes props and fires events. style (or a <style> inside the template) goes into the document head once per component. By default it is not contained. With scoped, it is contained with @scope (tag). Browsers without @scope apply it uncontained. A <style> inside <template h-component> works the same way. {{ }} in the template is also read only on an element with h-text-inline. Set on the component tag, it reads the text passed in as the slot.
Provides a value to the whole document. Any scope injects it with h-inject or $inject. If the key already exists, the existing value is returned, so it survives across visits.
The core's reactivity. An extension uses it to create its own state. If an extension file bundles its own reactivity library, the page cannot follow those values, so use the ones received here. $v is built this way.
A name registered with define is one for the whole document. A tool that depends on the scope element is registered with defineScoped. Each time an expression reads that name, it receives the handle of the scope that read it (host.el is the scope element) and builds the value. $tf is built this way.
turbo-drive is built with the tools below. Use the same ones to work with other libraries that swap out the page.
| Tool | What it does |
|---|---|
detach(selector) | Matching elements do not share the lifetime of the enclosing scope. They stay when the enclosing scope is torn down. When they leave the document, the runtime waits one tick before deciding |
snapshot() | Attaches each mounted scope's pre-mount markup as an attribute. The page stays as it is. The returned function removes the marks |
onRevive(fn) | Called right before a marked dead clone is mounted again. If anything needs to move from the dead copy to the new one, do it here |
onStop(fn) | Called when the runtime stops. Removes the listeners the extension added |
defineScoped does not reach scopes that are already mounted. Load it in head or call it before start().$scope, $host, or $refs logs a console error and is ignored.$. They are not confused with scope values, and they do not clash when a user creates state with the same name.