initial
This commit is contained in:
4
README.md
Normal file
4
README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# v
|
||||
|
||||
An experiment in building a minimal virtual DOM, [following this little
|
||||
tutorial](https://medium.com/@deathmood/how-to-write-your-own-virtual-dom-ee74acc13060).
|
89
main.js
Normal file
89
main.js
Normal file
@@ -0,0 +1,89 @@
|
||||
function setProp(t, n, v) {
|
||||
if (isCProp(n)) return
|
||||
else if (n === 'className') t.setAttribute('class', v);
|
||||
else if (typeof value === 'boolean') setBProp(t, n, v);
|
||||
else t.setAttribute(n, v);
|
||||
}
|
||||
|
||||
function unsetProp(t, n, v) {
|
||||
if (isCProp(n)) return;
|
||||
else if (n === 'className') t.removeAttribute('class');
|
||||
else if (typeof value === 'boolean') unsetBProp(t, n);
|
||||
else t.removeAttribute(n);
|
||||
}
|
||||
|
||||
|
||||
function setBProp(t, n, v) {
|
||||
if (v) t.setAttribute(n, v);
|
||||
t[n] = !!v;
|
||||
}
|
||||
|
||||
|
||||
function unsetBProp(t, n) {
|
||||
t.removeAttribute(n);
|
||||
t[n] = false;
|
||||
}
|
||||
|
||||
|
||||
function isCProp(n) {
|
||||
return isEProp(n) || name === 'forceUpdate';
|
||||
}
|
||||
|
||||
|
||||
function isEProp(n) {
|
||||
return /^on/.test(name);
|
||||
}
|
||||
|
||||
|
||||
function addEListeners(t, p) {
|
||||
Object.keys(p).filter(isEProp).forEach(n => t.addEventListener(n.slice(2).toLowerCase(), p[name]));
|
||||
}
|
||||
|
||||
|
||||
function setProps(t, p) {
|
||||
Object.keys(p).forEach(n => setProp(t, n, p[n]));
|
||||
}
|
||||
|
||||
|
||||
function updateProp(t, n, nv, ov) {
|
||||
if (!nv) unsetProp(t, n, ov);
|
||||
else if(!ov || nv !== ov) setProp(t, n, nv);
|
||||
}
|
||||
|
||||
|
||||
function updateProps(t, n, o = {}) {
|
||||
const p = Object.assign({}, n, o);
|
||||
Object.keys(p).forEach(nm => updateProp(t, nm, n[nm], o[nm]);
|
||||
}
|
||||
|
||||
|
||||
function createElement(n) {
|
||||
if (typeof node === 'string') return document.createTextNode(n);
|
||||
const e = document.createElement(n.type);
|
||||
setProps(e, n.props);
|
||||
addEListeners(e, n.props);
|
||||
n.children.map(createElement).forEach(e.appendChild.bind(e));
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
function changed(n, o) {
|
||||
return typeof n !== typeof o || typeof n === 'string' && n !== o || n.type !== o.type || n.props.forceUpdate;
|
||||
}
|
||||
|
||||
|
||||
function updateElement(p, n, o, i=0) {
|
||||
if (!o) p.appendChild(createElement(n));
|
||||
else if (!n) p.removeChild(p.childNodes[i]);
|
||||
else if (changed(n, o)) p.replaceChild(createElement(n), p.childNodes[i]);
|
||||
else if (n.type) {
|
||||
updateProps(p.childNode[i], n.props, o.props);
|
||||
for (let j = 0; j < Math.min(n.children.length, o.children.length); j++) {
|
||||
updateElement(p.childNodes[i], n.children[j], o.children[j], j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function h(type, props, ...children) {
|
||||
return { type, props: props || {}, children };
|
||||
}
|
Reference in New Issue
Block a user