Introduction to creating DOM elements with yo-yo.js

What is this

yo-yo is a cute name for a module that creates and updates DOM elements. You can use it in place of modules like react or virtual-dom.

Some features of yo-yo:

  • Use yo-yo in the browser or on the server
  • Instead of using a virtual DOM like react, yo-yo uses the actual DOM to diff changes and make efficient updates
  • No need for JSX. Instead yo-yo uses tagged template literals, a built-in feature of JavaScript
  • Small file size (4kb minified and gzipped)
  • No huge dependencies or devDependencies
  • You can support older browsers using the yo-yoify browserify transform

How to use yo-yo

Here are a few yo-yo usage examples to get you started.

Follow along:

  • create a directory for this example code
  • install yo-yo with npm: npm install yo-yo
  • create a file named index.js to type in examples
  • install budo, a development server for browserify: npm install -g budo

Creating elements

To create an element, require the yo-yo module, then put html inside of the backticks after yo:

var yo = require('yo-yo')

var element = yo`
  <p>hi</p>
`

Attaching elements to the DOM

There's nothing fancy about attaching an element made with yo-yo to the DOM. Use appendChild to attach the element to the body or any other existing html:

var yo = require('yo-yo')

var element = yo`
  <p>hi</p>
`

document.body.appendChild(element)

Using variables

A nice part about template literals is the ability to interpolate values into the string:

var yo = require('yo-yo')

var message = 'oh cool'

var element = yo`
  <p>${message}</p>
`

document.body.appendChild(element)

Updating elements

To update an element we use the yo.update method. The first argument to yo.update is the existing element you want to update. The second argument is the element with the new changes that you want to add to the DOM. In this example we increase the count variable every second:

var yo = require('yo-yo')

var count = 0

var element = yo`
  <p>count: ${count}</p>
`

setInterval(function () {
  count++
  var newElement = yo`
    <p>count: ${count}</p>
  `
  yo.update(element, newElement)
}, 1000)

document.body.appendChild(element)

Updating elements in response to user input

We can use an onclick handler on a <button> element to update the count rather than updating every second:

var yo = require('yo-yo')

var count = 0

var element = yo`
  <p>count: ${count}</p>
`

var input = yo`
  <button onclick=${onclick}>increase count</button>
`

function onclick () {
  count++
  var newElement = yo`
    <p>count: ${count}</p>
  `
  yo.update(element, newElement)
}

document.body.appendChild(element)
document.body.appendChild(input)

Simplifying multiple elements with a render function

The above example is a little messy with the duplicate document.body.appendChild statements and multiple elements created with yo.

Let's clean up the example by using a render function that returns the DOM node created by yo. Note that when we have multiple elements we have to wrap it in a parent element so that there is only one root element:

var yo = require('yo-yo')

var count = 0

function render () {
  return yo`
    <div id="app">
      <p>count: ${count}</p>
      <button onclick=${onclick}>increase count</button>
    </div>
  `
}

var app = render()

function onclick () {
  count++
  var update = render()
  yo.update(app, update)
}

document.body.appendChild(app)

Supporting older browsers

It's recommended to use browserify to bundle JS dependencies when using yo-yo. Additionally you can use the yo-yoify transform for browserify to convert tagged template literals into plain DOM-related JavaScript.

Example of setting up browserify & yo-yoify

Install as devDependencies:

npm install --save-dev browserify yo-yoify

Create a bundle npm script in your package.json file:

"scripts": {
  "browserify index.js -t yo-yoify -p bundle.js"
}

Related projects

choo

choo is a pleasant little framework based on yo-yo and a handful of other small modules. Check it out if you're looking for a higher-level approach, or to get a sense of how yo-yo might fit into a larger project.

bel & morphdom

yo-yo's dependencies are bel and morphdom. bel in turn uses hyperx to create DOM nodes from the tagged template literals, and morpddom provides the DOM diffing functionality. Try them out if you're looking for a lower-level approach to tagged template strings and DOM diffing, or want to learn more about how yo-yo works.

Seth Vincent

Seth makes weird arcades, writes JavaScript, and builds civic technology.
sethvincent.com
twitter.com/sethdvincent
github.com/sethvincent