JSFiddle - React, Tailwind, and code Playground
by wass80
HTML
<div id="main">
</div>
<button onclick="runner.next()">Step</button><br>
<textarea id="log" style="height: 600px; width: 100%;"></textarea>
JavaScript
const log = (text) => {
document.getElementById("log").value += text + "\n";
};
class VDOM {
constructor(tag, attrs, children) {
this.tag = tag;
this.attrs = attrs;
this.children = children;
this.dom = null;
}
render(parent) {
log(`Render ${this.tag}`);
this.initElement();
this.updateAttrs();
parent.appendChild(this.dom);
for (let child of this.children) {
child.render(this.dom);
}
}
update(parent, after) {
log(`Update? ${this.tag} -> ${after.tag}`)
if (this.tag !== after.tag || this.tag === "text" && this.attrs.text !== after.attrs.text) {
log(` Renew dom`)
after.initElement();
this.dom.replaceWith(after.dom);
this.dom = after.dom;
this.tag = after.tag;
this.children = [];
}
this.attrs = after.attrs;
this.updateAttrs();
if (after.tag === "text") return;
const [befores, afters] = [this.children.length, after.children.length];
const updates = Math.min(befores, afters);
for (let i = 0; i < updates; i++) {
log(` Change? #${i}`)
this.children[i].update(this.dom, after.children[i]);
}
for (let i = updates; i < befores; i++) {
log(` Delete #${i}`)
this.children[i].dom.remove();
this.children.splice(i, 1);
}
for (let i = updates; i < afters; i++) {
log(` New #${i}`)
after.children[i].render(this.dom);
this.children.push(after.children[i]);
};
}
initElement() {
if (this.tag === "text") {
this.dom = document.createTextNode(this.attrs.text);
return;
}
this.dom = document.createElement(this.tag);
}
updateAttrs() {
if (this.tag == "text") return;
for (let attr of this.dom.attributes) {
if (!this.attrs[attr.name]) this.dom.removeAttribute(attr.name);
}
for (const [name, value] of Object.entries(this.attrs)) {
this.dom.setAttribute(name, value);
}
}
}
const d = (tag, attrs, children) => new VDOM(tag, attrs, children);
const t...