Edit on
<h2>Understanding JSX</h2>

<p>
	This is an HTML page with a single babel-transpiled JS file and no dependencies.
	It is rendering DOM via JSX without any frameworks.
</p>
body {
	padding: 20px 20px 320px;
}
* {
	box-sizing: border-box;
}
pre {
	position: absolute;
	bottom: 0;
	left: 0;
	width: 100%;
	max-height: 300px;
	padding: 10px;
	margin: 0;
	background: #F3F3F3;
	border-top: 1px solid #CCC;
	box-shadow: inset 0 1px 10px rgba(0,0,0,0.2);
	font: 11px/1.1 Menlo,Monaco,'Courier New',courier;
	color: #555;
	overflow: auto;
}
View Compiled
/** @jsx h */

// ^^^^ this tells a transpiler to inject calls to an `h()` function for each node.

const ITEMS = 'hello there people'.split(' ');

// a "partial" that does a filtered loop - no template BS, just functional programming:
function foo(items) {
	// imagine templates that adhere to your JS styleguide...
	return items.map( p => <li> {p} </li> );		// <-- can be multiline
}

// a simple JSX "view" with a call out ("partial") to generate a list from an Array:
let vdom = (
	<div id="foo">
		<p>Look, a simple JSX DOM renderer!</p>
		<ul>{ foo(ITEMS) }</ul>
	</div>
);

// render() converts our "virtual DOM" (see below) to a real DOM tree:
let dom = render(vdom);

// append the new nodes somewhere:
document.body.appendChild(dom);

// Remember that "virtual DOM"? It's just JSON - each "VNode" is an object with 3 properties.
let json = JSON.stringify(vdom, null, '  ');

// The whole process (JSX -> VDOM -> DOM) in one step:
document.body.appendChild(
	render( <pre>{ json }</pre> )
);





/** Render Virtual DOM to the real DOM */
function render(vnode) {
	if (typeof vnode==='string') return document.createTextNode(vnode);
	let n = document.createElement(vnode.nodeName);
	Object.keys(vnode.attributes || {}).forEach( k => n.setAttribute(k, vnode.attributes[k]) );
	(vnode.children || []).forEach( c => n.appendChild(render(c)) );
	return n;
}

/** hyperscript generator, gets called by transpiled JSX */
function h(nodeName, attributes, ...args) {
	let children = args.length ? [].concat(...args) : null;
	return { nodeName, attributes, children };
}


/*
// here's an alternative hyperscript-to-vdom method that creates sparse nodes:
function h(nodeName, attributes, ...args) {
	let vnode = { nodeName };
	if (attributes) vnode.attributes = attributes;
	if (args.length) vnode.children = [].concat(...args);
	return vnode;
}
*/
View Compiled
Rerun