Snabbdom is a small Virtual DOM library. Unlike React, it's not a full View framework, it just focuses on the core virtual DOM problem : construct virtual DOM trees (virtual nodes) and patch the real DOM with them. it's entirely up to you to decide when those operations will happen. The main benefit is that you can adopt whatever architectural UI pattern you like in your application.
- Transforms Babel JSX templates into Snabbdom virtual nodes
- Straightforward mapping from JSX attributes to Snabbdom data attributes using namespaces
- JSX Components are simple functions
(attributes, children) => vnode. No more messy classes.
npm install snabbdom-jsx
Hello example (see the complete example here)
/** @jsx html */;const patch = snabbdom;const vnode = <div>Hello JSX</div>;
/** @jsx html */ pragma at the top tells Babel to use the
html function instead
of the React.createElement default. The
html function takes arguments passed from Babel
and generates virtual nodes as expected by Snabbdom's
Mapping JSX attributes
A quick reminder: in snabbdom, most of the functionality like toggling classes, styles and setting properties on DOM elements is delegated to separate modules.
const myInput =
Each module handles a portion of the data attributes (the 2nd parameter to
each portion is stored inside a namespace, for example, event attributes are placed
on namespace, class attributes inside the
class namespace and so on.
By default all attributes listed in the JSX element are placed inside the
<input type="text" />
Is equivalent to
To attach event listeners, we use the
<button on-click= callback />// is equivalent to
This is a generic rule to map a JSX attribute to a specific module, you need to prefix
the attribute with
pref is the namespace used by the module in Snabbdom.
As in the example above, all attributes with the
on- prefix (i.e. event listeners) will
be placed inside the the
on namespace. This gives us a simple and extensible pattern to
support other custom modules.
Another example using the
<divclass-visible=isVisibleclass-enabled=isEnabled>...</div>// is equivalent to
But you can also specify an unique object the same way as in the
h function, this is
useful when you have a dynamic object
<divstyle= fontWeight: 'bold' color: 'red' >...</div>// is equivalent to
You can mix both styles, the result will be a merge of all attributes
<divclass= visible: isVisibleclass-enabled=isEnabled>...</div>
Id and static classes (sel attribute)
In Snabbdom you can create an element using a css-like syntax
This will set the element id add the class names to its classList property. Unlike
classes specified in the
class namespace, those are static classes meaning they
will not be re-updated during patch operations.
In JSX you can use the
selector attribute to set the element's id and add static classes
<div selector="#id.class1.class2" />
You can also specify static classes via the
<div classNames="class1 class2" />
You can also provide an array to
classNames instead of a string
const classes = 'class1' 'class2';<div classNames=classes />
it's important to remember to not pass dynamic values to
As this can lead to some unexpected issues. If you want to set dynamic classes, use
the class module instead.
In React/JSX you can create components and use them inside other components
var HelloMessage = React;React;
Instead of classes, Snabbdom-jsx components are simple functions of type
(attributes, children) => vnode.
//HelloMessage : (attrs, body) -> vnodeconst HelloMessage =<div on-click= >name</div>;var vnode = <HelloMessage name="Yassine" />
As in React, note that all components must start with a capital letter, while regular HTML tags start with lower case letters. This the way Babel also distinguish component invocation from simple tag creation.
Perhaps of less obvious utility, but instead of a function, a component can also be an
object with a
render function. I added this in order to support nesting in
UI patterns; especially in the Elm architecture, where a component is an object with a
render) function (among others)
for example you can have a
Task ...Taskupdate = ...
and use it inside a
Todos component like this
As illustrated above, you can also add a
key attribute directly to a Component.
It will be copied inside the resulting vnode
If you're wondering how Components would fit in a large application, you can look into the todomvc example. The application is implemented using the Elm architecture. For more information see React-less Virtual DOM with Snabbdom : functions everywhere!