Skip to content

Instantly share code, notes, and snippets.

@rszewczyk
Last active August 29, 2015 14:19
Show Gist options
  • Save rszewczyk/bdf5c6ed31dc063bc693 to your computer and use it in GitHub Desktop.
Save rszewczyk/bdf5c6ed31dc063bc693 to your computer and use it in GitHub Desktop.
VDOM Example
<!doctype html>
<html>
<head>
<script src="http://fb.me/react-0.13.1.js"></script>
</head>
<body>
<div id="main"></div>
<script src="./bundle.js"></script>
</body>
</html>
/*
* My own experiment with a general purpose VDOM, based on the ideas presented here:
* https://gcanti.github.io/2014/10/29/understanding-react-and-reimplementing-it-from-scratch-part-1.html
*
* The basic takeaway is that a VDOM makes it possible to write declarative view logic
* with idiomatic javascript that is composable and free of side effects. This makes it possible
* to write our UI as components that are easy to reason about and test without
* using underpowered or overly verbose templating languages. We also get to treat
* the actual DOM as an external concern and are thus freed from a hole host of
* headaches that come with imperative DOM manipulation. For me, this is by far the most
* compelling case for using React.
*
* TODO: This would be more interesting with a less trivial example and with a more feature complete VDOM
*/
/*
function dom(tag, attributes, children) {
return {
tag: tag,
attributes: attributes,
children: children
};
}*/
//While the above is a nice convenient example
//for the purposes of the presentation - in order
//to render this VDOM with React it needs to be in
//a slightly different format. Alternatively
//we could translate the above "Universal VDOM" into
//React, Mithril, etc..
// see: https://github.com/gcanti/uvdom
function dom(tag, attributes, children) {
attributes.children = children;
return {
type: tag,
props: attributes,
_isReactElement: true
};
}
function domFactory(tag) {
return dom.bind(null, tag);
}
const div = domFactory('div');
const h3 = domFactory('h3');
const span = domFactory('span');
const hr = domFactory('hr');
const p = domFactory('p');
const li = domFactory('li');
const ul = domFactory('ul');
const h1 = domFactory('h1');
function blogComments(comments) {
return ul({}, comments.map(comment => li({ className: 'comment' }, comment)));
}
function blogPost({ title, date, author, content, comments }) {
return div({ className: 'post' }, [
h3({}, title),
span({ className: 'byline' }, `${date} by ${author}`),
hr({}),
p({ className: 'content' }, content),
blogComments(comments)
]);
}
function blog({ title, posts }) {
return div({ className: 'blog' }, [
h1({}, title),
div({}, posts.map(post => blogPost(post)))
]);
}
let data = {
title: "Lorem ipsum dolor sit.",
posts: [{
title: "Donec Sed Condimentum Nisi",
content: "Morbi quis nunc non orci vestibulum dapibus. Fusce tempus, risus sit amet scelerisque volutpat, sem ex luctus. Nam et egestas tortor, sed imperdiet odio. Pellentesque facilisis mauris urna, a suscipit tellus volutpat et. Mauris lacinia lobortis risus, ut faucibus ante hendrerit sed.",
date: "March 16, 2015",
author: "John Doe",
comments: [
"Quisque dictum quam non neque egestas.",
"Etiam pulvinar arcu vel felis vulputate, sit amet pretium ipsum rutrum.",
"Aenean elit mauris, finibus sit amet odio et, sollicitudin mollis risus."
]
}, {
title: "Bibendum Ultricies Dolor",
content: "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nunc ante purus, eleifend eu tincidunt in, eleifend sed sapien. Etiam ullamcorper, sem vehicula condimentum convallis, nisl nisi vehicula magna, quis auctor massa lacus sed urna.",
date: "March 10, 2015",
author: "Jane Doe",
comments: [
"Fusce ac ipsum vel sapien semper congue.",
"Aliquam at dictum velit. Suspendisse faucibus sit amet elit id tincidunt."
]
}]
}
let newPost = {
title: "Interdum Et Malesuada Fames",
content: "Pellentesque non elit ac justo venenatis tincidunt. Morbi at nulla orci. In sit amet purus cursus, suscipit enim ut, lobortis augue. Etiam pulvinar arcu vel felis vulputate, sit amet pretium ipsum rutrum. Aenean elit mauris, finibus sit amet odio et, sollicitudin mollis risus.",
date: "March 25, 2015",
author: "Bob Smith",
comments: [
"Morbi finibus ullamcorper lorem id ornare.",
"Curabitur volutpat nec dui ac tempus."
]
}
// Compile with
// 1. npm install -g babel
// 2. babel main.js --out-file bundle.js
//
//
// Run (from the browser console) with...
//
// 1. React.render(blog(data), document.getElementById('main'))
// 2. data.posts.unshift(newPost)
// 3. React.render(blog(data), document.getElementById('main'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment