Elements
Lightview is uniquely flexible. It doesn't force you into a single way of describing your DOM. Whether you prefer concise JavaScript functions, structured JSON, or standard HTML, the same signal-based reactivity powers it all.
Comparison
| Syntax | Style | Best For | Requirement |
|---|---|---|---|
| Tagged API | div(h1('Title')) |
Application logic, dynamic UIs | Core |
| vDOM | { tag: 'div', ... } |
Serialization, data-driven UI | Core |
| Object DOM (oDOM) | { div: { ... } } |
Concise templates, config files | Lightview X |
| Custom Elements | <lv-button> |
Progressive enhancement, CMS | Lightview X |
| cDOM (Experimental) | 'sum($/cart/items...price)' |
Declarative logic, LLM generation | lightview-cdom.js |
Note: An exciting 5th option is coming, the Computational DOM, a.k.a. cDOM.
Tagged API
Inspired by Bau.js, this is the most concise way to build UIs in JavaScript. Every HTML tag is available as a function.
const { signal, tags, $ } = Lightview;
const { div, h1, p, button } = tags;
const count = signal(0);
const app = div({ class: 'container' },
h1('Hello Lightview'),
p(() => `Count: ${count.value}`),
button({ onclick: () => count.value++ }, 'Click me')
);
$('#example').content(app);
Pros: Extremely readable, feels like "HTML in JS" without a compiler, full IDE autocomplete.
vDOM Syntax
Represent your UI as plain JavaScript objects. This is the underlying format for all non-string elements in Lightview.
const { signal, element, $, tags } = Lightview;
const { div } = tags;
const count = signal(0);
// will accept either a function or string as tag, function avoids typos better
const app = { tag:div, attributes: { class: 'container' }, children: [
{ tag: 'h1', attributes: {}, children: ['Hello Lightview'] },
{ tag: 'p', attributes: {}, children: [() => `Count: ${count.value}`] },
{ tag: 'button', attributes: { onclick: () => count.value++ }, children: ['Click me'] }
]};
$('#example').content(app);
Pros: Unambiguous, easy to serialize/deserialize as JSON, perfect for programmatic generation.
Object DOM (oDOM)
A more compact JSON representation provided by Lightview X. In oDOM, an object with a
single key and an object value represents an element. The key is the
tag name (e.g., "div", "span") or a custom element
function name. The value object contains the element's attributes.
Reserved Keys
Certain keys on the value object are reserved and have special meaning instead of being treated as attributes:
| Key | Purpose |
|---|---|
children |
An array of child elements, strings, or reactive functions. |
attributes |
An explicit attributes object (not needed in oDOM since non-reserved keys are attributes). If you use this attribute, Lighview MAY assume you are trying to use vDOM not oDOM. Avoid its use except for vDOM. |
tag |
Explicitly sets the tag name. If you use this attribute, Lighview MAY assume you are trying to use vDOM not oDOM. Avoid its use except for vDOM. |
All other keys on the value object are treated as attribute names. Keys starting with
on (like onclick, onmouseenter) are bound as event handlers.
Array Shorthand
If a tag key has an array as its value instead of an object, it is shorthand for
{ <key>: { children: <array> } }:
// These are equivalent:
{ ul: [{ li: ['Item 1'] }, { li: ['Item 2'] }] }
{ ul: { children: [{ li: { children: ['Item 1'] } }, { li: { children: ['Item 2'] } }] } }
Example
const { signal, tags, $ } = Lightview;
const count = signal(0);
const app = { div: { class: 'container', children: [
{ h1: ['Hello Lightview'] },
{ p: { children: [() => `Count: ${count.value}`] } },
{ button: { onclick: () => count.value++, children: ['Click me'] } }
]}};
$('#example').content(app);
Pros: Highly readable for templates stored in JSON, significantly less boilerplate than standard vDOM.
HTML Custom Elements
Use standard HTML tags to instantiate Lightview components. Ideal for multi-page apps or content managed by a CMS.
<!-- Requires registered components & Lightview X -->
<lv-card>
<h3 slot="title">User Profile</h3>
<lv-badge color="primary">Admin</lv-badge>
<p>Active since 2024</p>
<lv-button onclick="alert('Clicked!')">Settings</lv-button>
</lv-card>
Pros: Familiar HTML syntax, framework-agnostic, excellent for progressive enhancement of server-rendered pages.
Pseudo-elements
Lightview supports special "pseudo-elements" that perform specific tasks rather than creating a standard HTML element.
shadowDOM
The shadowDOM tag allows you to attach a Shadow Root to the parent element and render children
inside it. This is useful for building encapsulated components without manual attachShadow
calls.
const { tags } = Lightview;
const { div, shadowDOM, h2, p } = tags;
const MyComponent = () => div(
shadowDOM({ mode: 'open', styles: ['/my-styles.css'] },
h2('Encapsulated Title'),
p('This content is inside the shadow root.')
)
);
text
The text tag creates a single Text node containing the concatenated content of all
its children, separated by spaces. It supports reactivity, meaning if any child is a function, the text node
will update automatically.
const { tags, signal } = Lightview;
const { div, text } = tags;
const firstName = signal('John');
const lastName = signal('Doe');
const greeting = div(
text('Hello,', () => firstName.value, () => lastName.value, '!')
);
// Initial result: Hello, John Doe !
Events
Use standard event handlers prefixed with "on".
button({
onclick: (e) => handleClick(e),
onmouseenter: () => setHovered(true),
onmouseleave: () => setHovered(false)
})
Children
Children can be strings, numbers, elements, arrays, or functions:
div(
'Static text', // String
42, // Number (converted to string)
span('Nested element'), // Element
() => `Dynamic: ${value.value}`, // Reactive function
() => items.value.map(i => li(i.name)), // Reactive list
condition && span('Conditional') // Conditional (falsy = not rendered)
)
The domEl Property
Every Lightview element has a domEl property - the actual DOM node:
const myDiv = div({ class: 'box' }, 'Hello');
// Access the real DOM element
document.body.appendChild(myDiv.domEl);
// You can also manipulate it directly
myDiv.domEl.classList.add('another-class');