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...