yo-yo.js

In notebook:
FrontEndMasters Modular Web Development
Created at:
2017-10-01
Updated:
2017-10-02
Tags:
JavaScript libraries

yo-yo/bel/morphdom

yo-yo and bel are related libraries.

Yo-yo used hyperx and morphdom.

Morphdom: dom diffing with real DOM nodes

So it's like React but uses the real DOM. In their performance benchmarks, it's just as fast as React. (my note: the secret to its speed is that it only reads those DOM properties that don't trigger a reflow, so it can be quite fast)

  • faster in some cases than a virtual dom
  • interop with vanilla DOM modules

##Demo

Note: In the repo, this has been refactored to use choo

  //	****		yo.js		****

var html = require('yo-yo')
var n = 5
console.log(html`<div>
  <h1>${n}</h1>
</div>`
// for NodeJS ↴
.toString())

When you run this ($ node yo.js) in NodeJS you get a fake DOM tree. so you can add .toString in the end to visualise the result.

So now you have server side rendering!

If want to make it work in a real browser:

  //	****		yo.js		****

var html = require('yo-yo')
var n = 5

// **** 2. add a root element  ↴
var root = document.body.appendChild(document.createElement('div')) // appendChild will return the element appended

// **** 1 use html update  ↴
// need a root element to do the diffing on
html.update(root, html`<div> 
  <h1>${n}</h1>
</div>`)

Then he runs $ budo yo.js

budo will run the code in a browser with a web server. $ npm install -G budo

It runs browserify as well.

##Modifying state

  //	****		yo.js		****

var html = require('yo-yo')
var n = 5

var root = document.body.appendChild(document.createElement('div'))
// **** 2. run update first time the page loads  ↴
update()

// **** 3. create a timer that updates the state  ↴
setInterval(function () {
  n++
  // then call the update to re-render
  update()
}, 1000)


// **** 1. wrap it  ↴
function update () {
  html.update(root, html`<div> 
    <h1>${n}</h1>
  </div>`)
}

You can also have events hooked up,instead of the setInterval

  //	****		yo.js		****

var html = require('yo-yo')
var n = 5
// **** 2. add the counter  ↴
var x = 0

var root = document.body.appendChild(document.createElement('div'))
update()

setInterval(function () {
  n++
  update()
}, 1000)


function update () {
  html.update(root, html`<div> 
    <h1>${n}</h1>
    // **** 1.   ↴
    add the coaddunter display
    <div>${x}</div>
    // add the button ↴
    <button onclick=${onclick}>CLICK ME</button>
  </div>`)
  // **** 3. add the handler here  ↴
  function onclick (ev) {
    x++
    update()
  }
}

The final refactored code on GitHub:

  //	****		yo.js		****

var choo = require('choo')
var html = require('choo/html')
var wsock = require('websocket-stream')
var split = require('split2')
var to = require('to2')
var stream = wsock('ws://' + location.host)

var app = choo()
app.route('/', function (state, emit) {
  return html`<body>
    <h1>${state.visitors}</h1>
    <div>${state.x}</div>
    <button onclick=${onclick}>CLICK ME</button>
  </body>`
  function onclick (ev) {
    emit('increment-x')
  }
})
app.mount('body')

app.use(function (state, bus) {
  stream.pipe(split()).pipe(to(function (buf, enc, next) {
    bus.emit('set-visitors', Number(buf.toString()))
    next()
  }))
})
app.use(require('./reduce.js'))