A good introduction to JSX can be found here What is JSX
JSX is just a format that is used, the real work is done by the transpiler
the transpiler takes this form and calls a function with the args
/** @jsx transform
*/
let vdom = < div id = 'foo' > Hello !</ div > ;
// this will be executed as
let vdom = transform (
'div' ,
{ id : 'foo' } ,
'Hello !'
) ;
we can define the function and its return values
here babel transpiles the JSX and returns a JSON object with a node-name, its attributes and children
/** @jsx transform
*/
function transform ( nodeName , attributes , ...args ) {
let children = args . length ? [ ] . concat ( args ) :{ } ;
return { nodeName, attributes, children} ;
}
let vdom = < div id = 'foo' > Hello !</ div > ;
JSON . stringify ( vdom , null , 2 ) ;
{
"nodeName" : "div" ,
"attributes" : {
"id" : "foo"
} ,
"children" : [
"Hello !"
]
}
Getting started with Virtual DOM
I’m following the article here virtual dom part 1
virtual DOM is any kind of representation of the real DOM
we make a virtual DOM tree representation
we diff this virtual DOM tree with our real DOM tree
change our real DOM where it is needed
we leverage the JSX as mentioned above
a createElement function which adds new elements eg: <div>
function createElement ( vNode ) {
if ( typeof vNode === 'string' ) {
return document . createTextNode ( vNode ) ;
}
const parentElement = document . createElement ( vNode . type ) ;
vNode . children
. map ( createElement )
. forEach ( parentElement . appendChild . bind ( parentElement ) ) ;
return parentElement ;
}
a changed function which compares 2 tree node elements
function changed ( node1 , node2 ) {
return typeof node1 !== typeof node2 ||
typeof node1 === 'string' && node1 !== node2 ||
node1 . type !== node2 . type ;
}
an updateElement function which updates our real DOM where necessary
function updateElement ( rDom , newNode , oldNode , index = 0 ) {
if ( ! oldNode ) {
rDom . appendChild (
createElement ( newNode )
) ;
} else if ( ! newNode ) {
rDom . removeChild ( rDom . childNodes [ index ] ) ;
} else if ( changed ( newNode , oldNode ) ) {
rDom . replaceChild ( createElement ( newNode ) , rDom . childNodes [ index ] ) ;
} else if ( newNode . type ) {
const newLength = newNode . children . length ;
const oldLength = oldNode . children . length ;
for ( let i = 0 ; i < newLength || i < oldLength ; i ++ ) {
updateElement ( rDom . childNodes [ index ] , newNode . children [ i ] , oldNode . children [ i ] , i ) ;
}
}
}
a more practical virtual dom tutorial can be found here