“You don't need React to use Virtual DOM”

Illarion Koperski

2016-07-13

@illarionvk

“A virtual DOM is nice because it lets us write our code as if we were re-rendering the entire scene”

Matt Esch
author of virtual-dom module

 

Virtual DOM advantages

Using Virtual DOM, we can:

  • Use declarative way of representing the DOM
  • Have a clean and maintainable rendering logic
  • Render views on client or on server
  • Move UI calculations to a separate thread (web worker)
  • Write better tests

Implementations

File sizes

from "Pocket-sized JS" talk by Henrik Joreteg

Cart widget example

The cart widget is updated when new data is received from the server.

Quantity adjustment buttons and the "remove" button send AJAX requests to the server.

widget image from Vanilla UI by PixelBudda

Main cycle

var diff = require('virtual-dom/diff'),
    patch = require('virtual-dom/patch'),
    createElement = require('virtual-dom/create-element'),
    render = require('./render.js');

Main cycle

var diff = require('virtual-dom/diff'),
    patch = require('virtual-dom/patch'),
    createElement = require('virtual-dom/create-element'),
    render = require('./render.js');

// Initial render

var tree = render({ items: [] });
var rootNode = createElement(tree);

document
  .getElementById('js-cart')
  .appendChild(rootNode);

Main cycle

var diff = require('virtual-dom/diff'),
    patch = require('virtual-dom/patch'),
    createElement = require('virtual-dom/create-element'),
    render = require('./render.js');

// Initial render

var tree = render({ items: [] });
var rootNode = createElement(tree);

document
  .getElementById('js-cart')
  .appendChild(rootNode);

// Patch DOM on updates using custom event

var updateWidget = function(evt, cart) {
  var newTree = render(cart);
  var patches = diff(tree, newTree);
  rootNode = patch(rootNode, patches);
  tree = newTree;
}
// updateWidget is run when new data comes from the server
$(document).on('store:cart', updateWidget)

Render function

var map = require('lodash/map'),
    h = require('virtual-dom/h');

module.exports = function(cart) {
  return h('div', { className: 'Cart' }, map(cart.items, function(item) {
    return h('div', { className: 'Cart-item' }, [
      h('h3', { className: 'Cart-itemTitle' }, cart.item.title),
      h('p', { className: 'Cart-itemPrice' }, cart.item.price),
      h('button', {
        type: 'button',
        className: 'js-item-remove Cart-itemRemove',
        attributes: {
          'data-item-line': cart.item.line
        }
      }, 'Remove')
    ])
  }))
}

uses virtual-hyperscript, a DSL for creating virtual trees

concise - pure JS - lintable

Delegated event listeners

var $ = require('jquery');

$('#js-cart').on('click', '.js-item-remove', function(evt) {
  // Remove item from the cart on the server
});

$('#js-cart').on('click', '.js-item-qty-plus', function(evt) {
  // Increase item quantity
});

$('#js-cart').on('click', '.js-item-qty-minus', function(evt) {
  // Decrease item quantity
});

using jQuery

Resources

See you next month at WarsawJS

You don't need React to use Virtual DOM

By Illarion Koperski

You don't need React to use Virtual DOM

  • 1,300