• Stars
    star
    11,587
  • Rank 2,707 (Top 0.06 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 10 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Virtual DOM and diffing algorithm

virtual-dom

A JavaScript DOM model supporting element creation, diff computation and patch operations for efficient re-rendering

build status NPM version Coverage Status Davis Dependency status experimental Join the chat at https://gitter.im/Matt-Esch/virtual-dom

Sauce Test Status

Motivation

Manual DOM manipulation is messy and keeping track of the previous DOM state is hard. A solution to this problem is to write your code as if you were recreating the entire DOM whenever state changes. Of course, if you actually recreated the entire DOM every time your application state changed, your app would be very slow and your input fields would lose focus.

virtual-dom is a collection of modules designed to provide a declarative way of representing the DOM for your app. So instead of updating the DOM when your application state changes, you simply create a virtual tree or VTree, which looks like the DOM state that you want. virtual-dom will then figure out how to make the DOM look like this efficiently without recreating all of the DOM nodes.

virtual-dom allows you to update a view whenever state changes by creating a full VTree of the view and then patching the DOM efficiently to look exactly as you described it. This results in keeping manual DOM manipulation and previous state tracking out of your application code, promoting clean and maintainable rendering logic for web applications.

Example

var h = require('virtual-dom/h');
var diff = require('virtual-dom/diff');
var patch = require('virtual-dom/patch');
var createElement = require('virtual-dom/create-element');

// 1: Create a function that declares what the DOM should look like
function render(count)  {
    return h('div', {
        style: {
            textAlign: 'center',
            lineHeight: (100 + count) + 'px',
            border: '1px solid red',
            width: (100 + count) + 'px',
            height: (100 + count) + 'px'
        }
    }, [String(count)]);
}

// 2: Initialise the document
var count = 0;      // We need some app data. Here we just store a count.

var tree = render(count);               // We need an initial tree
var rootNode = createElement(tree);     // Create an initial root DOM node ...
document.body.appendChild(rootNode);    // ... and it should be in the document

// 3: Wire up the update logic
setInterval(function () {
      count++;

      var newTree = render(count);
      var patches = diff(tree, newTree);
      rootNode = patch(rootNode, patches);
      tree = newTree;
}, 1000);

View on RequireBin

Documentation

You can find the documentation for the seperate components in their READMEs

For information about the type signatures of these modules feel free to read the javascript signature definition

DOM model

virtual-dom exposes a set of objects designed for representing DOM nodes. A "Document Object Model Model" might seem like a strange term, but it is exactly that. It's a native JavaScript tree structure that represents a native DOM node tree. We call this a VTree

We can create a VTree using the objects directly in a verbose manner, or we can use the more terse virtual-hyperscript.

Example - creating a VTree using the objects directly

var VNode = require('virtual-dom/vnode/vnode');
var VText = require('virtual-dom/vnode/vtext');

function render(data) {
    return new VNode('div', {
        className: "greeting"
    }, [
        new VText("Hello " + String(data.name))
    ]);
}

module.exports = render;

Example - creating a VTree using virtual-hyperscript

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

function render(data) {
    return h('.greeting', ['Hello ' + data.name]);
}

module.exports = render;

The DOM model is designed to be efficient to create and read from. The reason why we don't just create a real DOM tree is that creating DOM nodes and reading the node properties is an expensive operation which is what we are trying to avoid. Reading some DOM node properties even causes side effects, so recreating the entire DOM structure with real DOM nodes simply isn't suitable for high performance rendering and it is not easy to reason about either.

A VTree is designed to be equivalent to an immutable data structure. While it's not actually immutable, you can reuse the nodes in multiple places and the functions we have exposed that take VTrees as arguments never mutate the trees. We could freeze the objects in the model but don't for efficiency. (The benefits of an immutable-equivalent data structure will be documented in vtree or blog post at some point)

Element creation

createElement(tree:VTree) -> DOMNode

Given that we have created a VTree, we need some way to translate this into a real DOM tree of some sort. This is provided by create-element.js. When rendering for the first time we would pass a complete VTree to create-element function to create the equivalent DOM node.

Diff computation

diff(previous:VTree, current:VTree) -> PatchObject

The primary motivation behind virtual-dom is to allow us to write code independent of previous state. So when our application state changes we will generate a new VTree. The diff function creates a set of DOM patches that, based on the difference between the previous VTree and the current VTree, will update the previous DOM tree to match the new VTree.

Patch operations

patch(rootNode:DOMNode, patches:PatchObject) -> DOMNode newRootNode

Once we have computed the set of patches required to apply to the DOM, we need a function that can apply those patches. This is provided by the patch function. Given a DOM root node and a set of DOM patches, the patch function will update the DOM. After applying the patches to the DOM, the DOM should look like the new VTree.

Original motivation

virtual-dom is heavily inspired by the inner workings of React by facebook. This project originated as a gist of ideas, which we have linked to provide some background context.

Tools

More Repositories

1

string-template

A lightweight string replace engine for text-based templates
JavaScript
272
star
2

vtree

A realtime tree diffing algorithm
JavaScript
128
star
3

vdom

A DOM create and patch algorithm for vtree
JavaScript
87
star
4

http-hash

HTTP router based on a strict path tree structure
JavaScript
75
star
5

http-hash-router

Server route handler for http-hash
JavaScript
34
star
6

underbar

Modular underscore - require("underbar/function")
JavaScript
21
star
7

anaconda

Anaconda is an open, cross-platform runtime for Anaconda for Multimedia Fusion 2, with support for Windows, Linux and Mac OS X.
Python
14
star
8

browser-fft

A cheap FFT by abusing the web audio API
JavaScript
12
star
9

virtual-form

Form interface for virtual-dom
JavaScript
11
star
10

x-is-array

JavaScript
9
star
11

biglist

Efficient rendering for large lists
JavaScript
9
star
12

css3d

Building 3D models using CSS 3D transforms on triangles
JavaScript
6
star
13

ptrack

A small collection of pitch tracking algorithms in C
6
star
14

blender-compiler

A high performance blend function compiler
JavaScript
5
star
15

eventsource-reconnect

JavaScript
4
star
16

isoblend

PDF Blend modes as defined by the Adobe® Supplement to the ISO 32000/-1
JavaScript
4
star
17

radial-camera

Computes the model view matrix for a camera rotated around a point
JavaScript
4
star
18

http-hash-server

HTTP server for http-hash router
JavaScript
4
star
19

c2-mode7

Mode7 pixel shader for Construct 2
FLUX
3
star
20

triangle-homography

JavaScript
3
star
21

triangle-buffer

JavaScript
3
star
22

event-source-server

Example server showing how to notify event-source-reconnect with keepalive messages
JavaScript
3
star
23

jsonml-document

JavaScript
3
star
24

x-is-string

JavaScript
3
star
25

jsonml-walk

JavaScript
3
star
26

simpleCanvas.js

An efficient JavaScript library for rendering rectangles, images and text.
JavaScript
3
star
27

opentty

Open a TTY read stream
JavaScript
3
star
28

c-playground

Playing around with clean and maintainable C styles
C
3
star
29

firstKey

JavaScript
2
star
30

canvas-blend

Blend overlapping images and draw the result
JavaScript
2
star
31

safe64

URI safe base64 encoding
JavaScript
2
star
32

text-assembler

Splits a string into multiple parts, identified by a guid.
JavaScript
2
star
33

arrow-keys

Arrow keys for all!
JavaScript
2
star
34

cssViewport

JavaScript
2
star
35

json-lookup

JavaScript
2
star
36

peer-module

JavaScript
2
star
37

node-tchannel-parser

TChannel frame parser for node.js
C++
1
star
38

isoblend-testbed

Compare isoblend implementation with output from Adobe® Photoshop®
JavaScript
1
star
39

unigl

Experimental portable GLES 2.0
C
1
star
40

choke

Rate limit a function call, and cancel waiting calls
JavaScript
1
star
41

sitemapper

Parallel web crawler for producing site maps
Go
1
star
42

strat

RTS engine - just for fun
C
1
star
43

x-is-object

JavaScript
1
star
44

xtendr

Extend with respect for undefined
JavaScript
1
star