Virtual DOM β
virtualDom.html β
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Virtual DOM</title>
</head>
<body>
<div id="root"></div>
<script>
/**
* Create Element
*
* @param {string} tagName HTML Tag Name
* @param {*} props Attributes & Children
* @returns {*} Element
*/
const createElement = (tagName, { attrs = {}, children = [] } = {}) => ({
tagName,
attrs,
children
});
/**
* Render
*
* @param {*} element TagName, Attributes & Children
* @returns {HTMLElement} HTML Element
*/
function render({ tagName, attrs = {}, children = [] }) {
const element = document.createElement(tagName);
// Append all children into the parent element
children.forEach(child => {
if (typeof child === "string") {
// If the child is a string, create a new text node object
element.appendChild(document.createTextNode(child));
} else {
// Else (re)call the render function, with the children elements
element.appendChild(render(child));
}
});
const attrsEntries = Object.entries(attrs);
// If there are attributes, it adds them to the parent element
if (attrsEntries.length) {
for (const [key, value] of attrsEntries) {
element.setAttribute(key, value);
}
}
return element;
}
/**
* Mount
*
* @param {HTMLElement} element
* @param {HTMLElement} rootElement
*/
function mount(element, rootElement) {
rootElement.replaceWith(element);
}
/* Components */
const titleElement = createElement("h1", {
attrs: { id: "title" },
children: ["Hello World"]
});
const loremIpsumElement = createElement("p", {
attrs: { class: "lorem-ipsum" },
children: ["Lorem ipsum dolor sit amet"]
});
const divElement = createElement("div", {
children: [titleElement, loremIpsumElement]
});
const element = render(divElement);
mount(element, document.getElementById("root"));
</script>
</body>
</html>