Ein leichtgewichtiges virtuelles DOM nach Art von Snabbdom. Es bildet deine Oberfläche als schlichte JavaScript-Objekte ab (die VNodes), vergleicht einen alten Baum mit einem neuen und trägt nur die Unterschiede ins echte DOM ein.
init() baut den Abgleicher und gibt eine patch-Funktion zurück. Die mitgelieferten Module (class / props / attrs / style / events) tragen sich von selbst ein.
patch(oldVnode, newVnode) hängt einen Baum ein (wenn oldVnode ein echtes DOM-Element ist) oder vergleicht zwei vnode-Bäume und bessert das DOM an Ort und Stelle nach.
h(sel, dataOrChildren?, children?) ist der Hyperscript-Helfer, der VNodes baut.
Hinweis: In dieser Umsetzung nimmt init()keine Argumente: Der Satz an Modulen liegt fest und wird intern eingetragen, die einzelnen *Module-Exporte müssen init also nicht übergeben werden. Exportiert sind sie zum Nachschlagen und Nachsehen.
import { init, h } from 'ranuts/vnode';// init() gibt eine `patch`-Funktion zurück.// Die mitgelieferten Module (class, props, attrs, style, events) tragen sich von selbst ein.const patch = init();const container = document.getElementById('app');// Einen vnode-Baum bauenlet vnode = h('div#app.container', { style: { color: 'red' } }, [ h('h1', 'Hello vnode'), h('button', { on: { click: () => console.log('clicked') } }, 'Click me'),]);// Erstes Zeichnen: als alten vnode ein echtes DOM-Element übergeben, dann wird darin eingehängtpatch(container, vnode);// Später: den aktualisierten Baum bauen und den vorigen vnode darauf patchen.// Ins DOM gelangen nur die Unterschiede (Text, Stil, Listener).const newVnode = h('div#app.container', { style: { color: 'green' } }, [ h('h1', 'Hello again'), h('button', { on: { click: () => console.log('clicked') } }, 'Updated'),]);patch(vnode, newVnode);vnode = newVnode; // den neuesten Baum für das nächste patch behalten
// nur das Tagh('div');// Tag + datah('div', { class: { active: true } });// Tag + ein einzelnes Textkindh('span', 'hello');// Tag + Array von Kindernh('ul', [h('li', 'one'), h('li', 'two')]);// Tag + data + Kinderh('a', { attrs: { href: '/home' } }, 'Home');// Selektoren im CSS-Stil legen id und Klassen festh('div#main.card.large', 'content'); // <div id="main" class="card large">content</div>// Der SVG-Namensraum wird von selbst gesetzt, wenn der Selektor mit "svg" beginnth('svg', { attrs: { width: 100, height: 100 } }, [h('circle', { attrs: { cx: 50, cy: 50, r: 40 } })]);
Kommt von init(). Übergib beim ersten Aufruf als oldVnode ein echtes DOM-Element, dann wird der Baum darin eingehängt. Bei späteren Aufrufen übergib den vorigen VNode, um an Ort und Stelle abzugleichen und nachzubessern. Zurück kommt der neue VNode, den du als „alten“ Wert für den nächsten Aufruf behältst.
HTML-Attribute, gesetzt über setAttribute (true und false schalten das Attribut ein und aus)
Record<string, string | number | boolean>
attributesModule
class
Bedingte Klassen: eine Zuordnung name → boolean
Record<string, boolean>
classModule
style
Inline-Stile: eine Zuordnung name → value (Schlüssel mit --var werden zu CSS-Variablen)
Record<string, any>
styleModule
on
Ereignis-Listener: event → handler (oder ein Array von Handlern)
Record<string, Function | Function[]>
eventListenersModule
key
Beständiges Kennzeichen, mit dem der Abgleich Kinder zuordnet und umsortiert
string | number
(Kern des Abgleichs)
ns
URI des Namensraums (bei SVG-Teilbäumen von selbst gesetzt)
string
(Kern des Abgleichs)
hook
Lebenszyklus-Hooks je vnode (Hooks)
Hooks
(nur als Typ: siehe Hinweis)
Hinweis: hook und der Typ Hooks gehören zur öffentlichen Typfläche. Diese abgespeckte Umsetzung steuert das DOM jedoch über den Lebenszyklus der Module (create / update / destroy); die data.hook-Rückrufe je vnode ruft die derzeitige patch-Schleife nicht auf.
Nur für den Browser.ranuts/vnode fasst document und die DOM-APIs an; importiere es in Browser-Code, nicht in Node.
Behalte den letzten vnode.patch gibt den neuen VNode zurück. Heb ihn auf und übergib ihn bei der nächsten Aktualisierung als oldVnode, damit gegen den aktuellen Baum verglichen wird.
In einem VNode schließen sich text und children aus: Ein Knoten ist entweder ein Textknoten oder ein Element mit Kindern.
Nimm key für Listen. Gib Geschwistern beim Zeichnen veränderlicher Listen beständige key-Werte, damit der Abgleich Knoten zuordnen und umsortieren kann, statt sie neu zu erzeugen.