{"id":15314653,"url":"https://github.com/unframework/virtual-dom","last_synced_at":"2025-10-09T00:32:22.359Z","repository":{"id":28873890,"uuid":"32398202","full_name":"unframework/virtual-dom","owner":"unframework","description":"A Virtual DOM and diffing algorithm","archived":false,"fork":true,"pushed_at":"2015-03-17T14:35:16.000Z","size":403,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-10-02T08:46:48.980Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Matt-Esch/virtual-dom","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unframework.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-17T14:27:13.000Z","updated_at":"2019-08-18T16:40:58.000Z","dependencies_parsed_at":"2023-07-04T17:40:36.309Z","dependency_job_id":null,"html_url":"https://github.com/unframework/virtual-dom","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unframework%2Fvirtual-dom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unframework%2Fvirtual-dom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unframework%2Fvirtual-dom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unframework%2Fvirtual-dom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unframework","download_url":"https://codeload.github.com/unframework/virtual-dom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235781122,"owners_count":19043929,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-01T08:46:32.336Z","updated_at":"2025-10-09T00:32:17.092Z","avatar_url":"https://github.com/unframework.png","language":"JavaScript","readme":"# virtual-dom\n\nA JavaScript [DOM model](#dom-model) supporting [element creation](#element-creation), [diff computation](#diff-computation) and [patch operations](#patch-operations) for efficient re-rendering\n\n[![build status][1]][2]\n[![NPM version][3]][4]\n[![Coverage Status][5]][6]\n[![Davis Dependency status][7]][8]\n[![experimental](http://hughsk.github.io/stability-badges/dist/experimental.svg)](http://github.com/hughsk/stability-badges)\n\n[![Sauce Test Status](https://saucelabs.com/browser-matrix/mattesch.svg)](https://saucelabs.com/u/mattesch)\n\n## Motivation\n\nManual 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.\n\n`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.\n\n`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.\n\n## Example\n\n```javascript\nvar h = require('virtual-dom/h');\nvar diff = require('virtual-dom/diff');\nvar patch = require('virtual-dom/patch');\nvar createElement = require('virtual-dom/create-element');\n\n// 1: Create a function that declares what the DOM should look like\nfunction render(count)  {\n    return h('div', {\n        style: {\n            textAlign: 'center',\n            lineHeight: (100 + count) + 'px',\n            border: '1px solid red',\n            width: (100 + count) + 'px',\n            height: (100 + count) + 'px'\n        }\n    }, [String(count)]);\n}\n\n// 2: Initialise the document\nvar count = 0;      // We need some app data. Here we just store a count.\n\nvar tree = render(count);               // We need an initial tree\nvar rootNode = createElement(tree);     // Create an initial root DOM node ...\ndocument.body.appendChild(rootNode);    // ... and it should be in the document\n\n// 3: Wire up the update logic\nsetInterval(function () {\n      count++;\n\n      var newTree = render(count);\n      var patches = diff(tree, newTree);\n      rootNode = patch(rootNode, patches);\n      tree = newTree;\n}, 1000);\n```\n[View on RequireBin](http://requirebin.com/?gist=5492847b9a9025e64bab)\n\n## Documentation\n\nYou can find the documentation for the seperate components\n  in their READMEs\n\n - For `create-element.js` see the [vdom README](vdom/README.md)\n - For `diff.js` see the [vtree README](vtree/README.md)\n - For `h.js` see the [virtual-hyperscript README](virtual-hyperscript/README.md)\n - For `patch.js` see the [vdom README](vdom/README.md)\n\nFor information about the type signatures of these modules feel\n  free to read the [javascript signature definition](docs.jsig)\n\n## DOM model\n\n`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**\n\nWe can create a VTree using the objects directly in a verbose manner, or we can use the more terse virtual-hyperscript.\n\n### Example - creating a VTree using the objects directly\n\n```javascript\nvar VNode = require('virtual-dom/vnode/vnode');\nvar VText = require('virtual-dom/vnode/vtext')\n\nfunction render(data) {\n    return new VNode('div', {\n        className: \"greeting\"\n    }, [\n        new VText(\"Hello \" + String(data.name));\n    ]);\n}\n\nmodule.exports = render;\n```\n\n### Example - creating a VTree using virtual-hyperscript\n\n```javascript\nvar h = require('virtual-dom/h');\n\nfunction render(data) {\n    return h('.greeting', ['Hello ' + data.name]);\n}\n\nmodule.exports = render;\n```\n\nThe 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.\n\nA `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)\n\n\n\n## Element creation\n\n```haskell\ncreateElement(tree:VTree) -\u003e DOMNode\n```\n\nGiven 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.\n\n## Diff computation\n\n```haskell\ndiff(previous:VTree, current:VTree) -\u003e PatchObject\n```\n\nThe primary motivation behind virtual-dom is to allow us to write code indepentent 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`.\n\n## Patch operations\n\n```haskell\npatch(rootNode:DOMNode, patches:PatchObject) -\u003e DOMNode newRootNode\n```\n\nOnce 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`.\n\n\n## Original motivation\n\nvirtual-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](https://gist.github.com/Raynos/8414846).\n\n## Tools\n\n* [html2hscript](https://github.com/twilson63/html2hscript) - Parse HTML into hyperscript\n* [html2hscript.herokuapp.com](http://html2hscript.herokuapp.com/) - Online Tool that converts html snippets to hyperscript\n* [html2hyperscript](https://github.com/unframework/html2hyperscript) - Original commandline utility to convert legacy HTML markup into hyperscript\n\n\n[1]: https://secure.travis-ci.org/Matt-Esch/virtual-dom.svg\n[2]: https://travis-ci.org/Matt-Esch/virtual-dom\n[3]: https://badge.fury.io/js/virtual-dom.svg\n[4]: https://badge.fury.io/js/virtual-dom\n[5]: http://img.shields.io/coveralls/Matt-Esch/virtual-dom.svg\n[6]: https://coveralls.io/r/Matt-Esch/virtual-dom\n[7]: https://david-dm.org/Matt-Esch/virtual-dom.svg\n[8]: https://david-dm.org/Matt-Esch/virtual-dom\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funframework%2Fvirtual-dom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funframework%2Fvirtual-dom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funframework%2Fvirtual-dom/lists"}