Getting Started
Install Regor, mount your first reactive view, and try it live.
Regor binds runtime behavior directly to DOM you already have, or to template content you provide at mount time.
This means you can start from static HTML, mount only where needed, and scale to multiple independent runtime islands on the same page.
Use your package manager or start with a browser module.
Bind existing HTML or supply a template for your app.
Use refs and events to make your view respond.
Install
npm install regor yarn add regor Quick Start (TypeScript)
Add a mount target to your HTML, then run your TypeScript entry after that element exists (for example, with a module script).
<div id="app"></div> The buttons update a ref. Regor updates the text bound to it.
One ref, an event handler, and a text binding.
import { html, ref } from 'regor'
export function createCounter(interactive = false) {
const count = ref(0)
return {
interactive,
count,
increment: () => count(count() + 1),
reset: () => count(0),
}
}
export const counterTemplate = html` <div class="guide-demo guide-demo--split">
<div class="guide-controls">
<strong>Change state. Watch the DOM.</strong>
<p>The buttons update a ref. Regor updates the text bound to it.</p>
<div class="guide-session-bar">
<button type="button" @click="increment" :disabled="!interactive">
Increment
</button>
<button type="button" @click="reset" :disabled="!interactive">
Reset
</button>
</div>
</div>
<div class="guide-readout">
<span class="guide-kicker">YOUR FIRST REF / COUNT</span>
<output
class="guide-total"
aria-label="Counter value"
aria-live="polite"
r-text="count"
></output>
<p>One ref, an event handler, and a text binding.</p>
</div>
</div>` import { createApp, useScope } from 'regor'
import { createCounter, counterTemplate } from './counter'
const element = document.getElementById('app')
if (element) {
const app = createApp(
useScope(() => createCounter(true)),
{ element, template: counterTemplate },
)
// When this root is no longer needed:
// app.unbind() // Stop bindings and listeners, keeping the DOM.
// app.unmount() // Stop bindings and listeners, removing the root.
} Click Increment, then Reset. Open the source tabs to see the state, template, and mount code used by this preview.
Regor binds to the element you select. Make sure its selector matches your HTML and that the element is present when createApp runs.
CDN ESM
<div id="app"></div>
<script type="module">
import {
createApp,
ref,
} from 'https://unpkg.com/regor/dist/regor.es2022.esm.prod.js'
createApp(
{
message: ref('Hello from CDN'),
},
{
element: document.querySelector('#app'),
template: '<h1 r-text="message"></h1>',
},
)
</script> Core Mount Modes
- Bind existing markup in place:
createApp({ userName: ref('Ada') }, { selector: '#profile-island' }) - Replace root content from template string:
createApp(
{ title: ref('Home') },
{
selector: '#app',
template: '<h1 r-text="title"></h1>',
},
) - Replace root content from JSON template:
createApp(
{ label: ref('Save') },
{
element: document.querySelector('#app')!,
json: { t: 'button', a: { 'r-text': 'label' } },
},
) Reactivity Basics
ref for values and deep object conversion:
import { ref } from 'regor'
const count = ref(0)
count(1)
console.log(count()) sref for shallow object state:
import { sref } from 'regor'
const user = sref({ name: 'Ada', age: 30 })
user().name = 'Grace'
user({ ...user(), age: 31 }) Inside templates, refs are auto-unwrapped, so use count, user.name, not count() or .value.
With sref, editing a plain nested property does not notify bindings by itself. Replace the object, as in the example above, to update the view.
Component Quick Example
import { createApp, defineComponent, ref } from 'regor'
const UserCard = defineComponent('<article><h3 r-text="name"></h3></article>', {
props: ['name'],
context: (head) => ({
name: head.props.name ?? 'Anonymous',
}),
})
createApp({
components: { UserCard },
activeName: ref('Ada Lovelace'),
}) <UserCard :name="activeName"></UserCard> Template Syntax You Will Use Daily
r-text="expr"for text.:attr="expr"orr-bind:attr="expr"for attributes..prop="expr"or:prop.prop="expr"for DOM properties.@event="handler"for events.r-if/r-else-if/r-elsefor conditional branches.r-for="item, #i in items"for loops.:context="{ ... }"/r-context="{ ... }"for object-style component input.{{ expr }}and[[ expr ]]interpolation (enabled by default).