virtual-dom README

The project's README from github.com/Matt-Esch/virtual-dom. As one markdown file: README.md.

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

virtual-dom (Matt-Esch/virtual-dom)

Searching Database…

这是什么东西?virtual-dom 是一个用 JavaScript 编写的库,用来对 DOM 建模:你把想要的界面描述成一棵虚拟树(VTree),它会高效地创建真实 DOM、比较差异(diff)并打补丁(patch),让重新渲染变得更快。
它是一个接管我整个应用的框架,还是一个我可以直接调用的库?它是一个库,不是框架——由一组需要你自己组装的模块组成:h.js(即 virtual-hyperscript)用来描述节点,create-element.js 根据 VTree 生成真实 DOM,diff.js 计算差异补丁,patch.js 负责把补丁应用到 DOM 上。
我怎么把它加到项目里?先安装这个 npm 包(npm install virtual-dom),然后 require 引入即可;另外也提供了一个独立打包好的浏览器版本(dist/virtual-dom.js)。每个模块的文档都放在各自的 README 里(vdom、vtree、virtual-hyperscript)。
运行它需要什么重型的东西吗——构建工具链、原生代码或者后端服务?不需要——它就是一个普通的 JavaScript npm 包,依赖的只是一些小工具库(browser-split、error、ev-store、global、is-object、next-tick、x-is-array、x-is-string),不涉及原生编译、Python 或任何后端服务。
当我的应用状态变化时,它会自己重新渲染吗?不会,需要你自己来驱动:每次状态变化后,你要自己生成一棵新的 VTree,然后对旧树调用 diff 计算差异,再把补丁应用到 DOM 上。树是不可变的——暴露出来的函数绝不会修改传入的树,所以应该新建一棵树,而不是直接改旧树。
一次更新是怎么经过 create-element、diff 和 patch 处理的?首次渲染时:把一棵完整的 VTree 传给 create-element,得到一个真实的 DOM 节点。更新时:先生成新的 VTree,调用 diff(previousTree, newTree) 计算出补丁,然后调用 patch(rootNode, patches) 更新 DOM,使它和新树保持一致。
为什么要对比虚拟树,而不是直接更新真实 DOM?创建 DOM 节点、读取它们的属性开销都很大——某些属性读取甚至会触发副作用。而纯 JavaScript 的树创建和读取都很便宜,所以这个库先算出两棵树之间的差异,只在真正变化的地方去操作 DOM。
它和 React 是什么关系?它的设计深受 Facebook 的 React 内部实现方式的启发,但它是一套独立的模块。这个项目最初只是一个汇集想法的 gist,README 里附了链接,供了解背景。
我能把现有的 HTML 标记转换成它用的格式吗?可以——README 里列出了 html2hscript(在 html2hscript.herokuapp.com 提供在线转换器)和 html2hyperscript 命令行工具,它们能把 HTML 片段和旧式标记解析成 hyperscript,用来构建 VTree。
What are similar projects?marked, inferno, typeahead.js, Sortable, masonry, velocity, snabbdom, lit
Creator
Matt-Esch
Size
0.8 MB
Stars
11.8K
Updated
CommitApr 22
Age
12y
Commits · 90 Days