Mathieu Schimmerling

  • Home
  • Writing

    Projects

  • CoinFeed.me

    Online

  • Twitter
  • Github

Writing

How to learn & understand every JS framework the right way !
false

How to learn & understand every JS framework the right way !

false

You want to learn React, VueJS, Svelte, Angular,… super fast ?! You are in the right place ! Or you are loosing your head to choose a JS framework because you are facing the endless framework war ?

All those frameworks have really common concepts, this is why:

  • The hardcore way: Read all the docs & read all source code & contribute to the project
  • The hard way: Learn pure JavaScript, DOM API, Browser API and reverse engineer framework core concepts
  • The common way: Pick any of these framework and practice it a lot.

With Vanilla JS

Understanding React & VueJS: Virtual DOM

To make a Virtual DOM, we must understand what is the DOM itself ? We know that the DOM contains HTML nodes. So what is composed a HTML node ?

  • A tag: div, span, p, h1,…
  • Attributes: class, id, label, value,…
  • Children HTML nodes: Contains zero, one or more HTML nodes.

Ok let’s recreate the DOM itself in JavaScript (alias Virtual DOM). First we need to create a function representing an HTML Node

function createVirtualNode(tag, attributes, childrenNodes) {
	tag = tag || '';
	attributes = attributes || {};
	childrenNodes = childrenNodes || [];

	return {
		tag,
		attributes,
		childrenNodes,
	};
}

Let’s determine the HTML structure we want to build:

<div id="header">
	<p>Hello <span class="bold text-pink">everybody</span> !</p>
	<img
		src="https://images.unsplash.com/photo-1600505386060-16d02c5626c3"
		alt="man cooking"
		style="width: 300px;"
	/>
</div>

Ok let’s use our function createVirtualNode to represent this structure. Analyze the following carefully.

const virtualDOM = createVirtualNode('div', { id: 'header' }, [
	createVirtualNode('p', {}, [
		'Hello ',
		createVirtualNode('span', { class: 'bold text-pink' }, ['everybody']),
		' !',
	]),
	createVirtualNode('img', {
		src: 'https://images.unsplash.com/photo-1600505386060-16d02c5626c3',
		alt: 'man cooking',
		style: 'width: 300px;',
	}),
]);

console.dir(virtualDOM, { depth: null });

Let’s see what our virtual DOM looks like:

{
  tag: 'div',
  attributes: { id: 'header' },
  childrenNodes: [
    {
      tag: 'p',
      attributes: {},
      childrenNodes: [
        'Hello ',
        {
          tag: 'span',
          attributes: { class: 'bold text-pink' },
          childrenNodes: [ 'everybody' ]
        },
        ' !'
      ]
    },
    {
      tag: 'img',
      attributes: {
        src: 'https://images.unsplash.com/photo-1600505386060-16d02c5626c3',
        alt: 'man cooking'
      },
      childrenNodes: []
    }
  ]
}

Whoow… that’s beautiful… right ?

But but what do we do now with this structure ? They are 2 big uses:

  • Render it to the real DOM !
  • Generating the corresponding HTML server-side and send an HTML page

Let’s render it to the real DOM first by creating the render function:

function renderDOMNode({ tag, attributes, childrenNodes }) {
	const node = document.createElement(tag);

	for (const attributeKey in attributes) {
		node.setAttribute(attributeKey, attributes[attributeKey]);
	}

	for (const childrenNode of childrenNodes) {
		if (typeof childrenNode === 'string') {
			node.appendChild(document.createTextNode(childrenNode));
		} else {
			node.appendChild(renderDOMNode(childrenNode));
		}
	}

	return node;
}

Let’s use it !

const node = renderVirtualNode(virtualDOM);

document.getElementById('app').appendChild(node);

HTML Preview:

function renderDOMNodeStr({ tag, attributes, childrenNodes }) {
	let node = `<${tag}`;

	for (const attributeKey in attributes) {
		node += ` ${attributeKey}="${attributes[attributeKey]}"`;
	}

	if (childrenNodes.length === 0) {
		node += '/>';
	} else {
		node += '>';
		for (const childrenNode of childrenNodes) {
			if (typeof virtualChildNode === 'string') {
				node += virtualChildNode;
			} else {
				node += renderDOMNodeStr(childrenNode);
			}
		}
		node += `</${tag}>`;
	}
	return node;
}

If we build a library for our VirtualDOM, it will look like this !

Now let’s see how to use our VirtualDOM server side:

Sources

  • https://indepth.dev/level-up-your-reverse-engineering-skills/