Virtual DOM frameworks are all the rage. But the real DOM is faster than you might think. Each time you call its dispatch function, Real-DOM simply replaces the entire DOM tree under its root node with your new view. This makes it simple and uncluttered. It's less than 50 lines of code before minifying, and roughly 1K after. It has built-in support for Redux-style actions and reducers, but also can be used more simply, by passing new state directly to the dispatch
function it passes to the view. The version in src
is in ES2015 module format and the version in dist
is in UMD module format.
Apps with thousands of DOM nodes or that frequently redraw their views may benefit significantly from avoiding DOM mutation. But most applications aren't that complex and do not update very frequently. If you are developing a game or the next Facebook, then you should probably consider using React or one of the many virtual DOM alternatives. If you just want typeahead results or simple todos, you won't really notice it.
Before replacing the view, Real-DOM stores a reference to the document's active element. After replacing the view, Real-DOM will return focus to the element with the same id
attribute. It also preserves caret position, selection, and scroll position for any element with an id
attribute. In modern browsers, this happens fast enough that it does not interrupt typing in a non-debounced controlled input.
Probably not very well. If you have a very complex DOM tree or redraw your view very frequently, it's not the right approach for you.
Yep. Here's the starter kit. Real-DOM registers itself on the global variable realDOM
.
Yes, if you configure Babel to use its h
function instead of React.createElement
. Keep in mind that Real-DOM does not have a simulated event system like React, and it doesn't accept other full React-style components as arguments. It does, though, accept functions (see the API documentation below). Due to how JSX is translated into function calls, the name of the function has to be capitalized. Here's an example.
Theoretically, but it has not been thoroughly tested. You'll need a synthetic document object, such as jsdom.
Real-DOM exposes only two functions: component
and h
. component
takes, at minimum, an initial state and a function that renders your view. It can also take a Redux-style reducer and a factory function for registering callbacks to external events, such as a Web Socket. h
is named in honor of hyperscript and follows the same syntax with some simplifications.
A function HTMLElement -> void
. When invoked, the function mounts the application as a child of that root node. The root node should not have any other children: they will be removed from the tree on each update of the view.
initialState
: the application's initial state. It accepts any value: object, array, primitive.view
: a function(state, dispatch) -> HTMLElement
. This function will be invoked withinitialState
when the application is mounted, and then again each time the dispatch function is called. The result will be appended as a child to the root node (see the return value above). Theh
function below is provided to make composing this function easier.reducer
: a function(state, action) -> *
. The value returned from the function becomes the application's new state. It is good practice for this to be a pure function. If the action it receives is aPromise
, it will execute after thePromise
resolves. The default is(state, action) => action
. That is, it sets the application's new state to whatever value is passed to thedispatch
function of the view.registerSubscriptions
: a functiondispatch -> void
. The function will be invoked immediately after the application is mounted. Use this function to register callbacks to external services, so that they can call the dispatch function, e.g., a Web Socket, firebase, meteor.
An HTMLElement
.
Either the tag name of the html element or a function. If it is invoked with a function, that function will be called with the value of the attrs
argument, similar to a stateless functional component in React.
An object containing the attributes to be applied to the html element. Use the JavaScript names for accessing attributes; for example, className
instead of class
. It supports registering events by passing functions for onevent
attributes. The only special handling is for the style attribute, which can take either a string or an object with individual CSS properties. It gracefully handles null
or undefined
.
If a function was passed to tag
, then that function will be executed with this parameter, without any parsing. (That includes null
and undefined
, which will be passed directly.)
Any remaining parameters are handled as children to the node. Strings are wrapped with a call to document.createTextNode
. Arrays are flattened and their elements handled as other parameters.