VIRT DOM

npm install @nathanfaucett/virt --save

npm install @nathanfaucett/virt-dom --save

 

virt is a tool for creating interactive UIs where you use abstract views for each state in your application, and virt will find the differences and create a Transaction. virt was created after reading facebook's React source code. The difference is virt creates JSON Transactions that an adapter like virt-dom uses to render to some native view system, in virt-dom's case the DOM.

virt-dom provides adapters to render virt changes to the DOM over a WebSocket, a WebWorker or from the main javascript thread. Examples of all three are below.

Real World Example

Full site example here http://bomontfii.com. github repo for virt views and application logic. github repo for building and starting application.

Some technical examples

Simple Example Usage

The best way to use virt is to create custom components that inherit from the virt.Component class.

var virt = require("@nathanfaucett/virt"), virtDOM = require("@nathanfaucett/virt-dom"); function List(props, children, context) { virt.Component.call(this, props, children, context); this.state = { items: [ {id: 0, text: "Item 1"}, {id: 1, text: "Item 2"} ] }; } // same as // List.prototype = Object.create(virt.Component.prototype); // List.prototype.displayName = "List"; virt.Component.extend(List, "List"); List.prototype.onClick = function(id) { var _this = this; this.state.items.forEach(function(value, index, array) { if (value.id === id) { array.splice(index, 1); _this.setState({ items: array }); return false; } }); }; List.prototype.render = function() { var _this = this; return ( virt.createView("ul", this.state.items.map(function(item) { return virt.createView(Item, { key: item.id, onClick: function onClick() { _this.onClick(item.id); }, text: item.text }); })) ); }; function Item(props, children, context) { virt.Component.call(this, props, children, context); } virt.Component.extend(Item, "Item"); Item.prototype.render = function() { return ( virt.createView("li", { onClick: this.props.onClick }, this.props.text) ); }; virtDOM.render(virt.createView(List), document.getElementById("app"));

Messeger

A messeger is how all data is sent and received between the views and the renderer. This is used internally to fix inconsistencies in native DOM elements. Native DOM Elements

var virt = require("@nathanfaucett/virt"); function HelloWorld(props, children, context) { virt.Component.call(this, props, children, context); } virt.Component.extend(HelloWorld, "example.HelloWorld"); HelloWorld.prototype.componentDidMount = function(id) { this.emitMessage("example.HelloWorld.mount", { id: this.getInternalId() }, // optional callback function onHandled(error, data) { if (error) { // handle error } else { // handle any data send from the handler } } ); }; HelloWorld.prototype.render = function() { return virt.createView("div"); }; var virtDOM = require("@nathanfaucett/virt-dom"); virtDOM.addNativeHandler( "example.HelloWorld.mount", function(data, doneCallback) { var id = data.id, node = findDOMNode(id); if (node) { node.innerHTML = "

Hello, world!

"; // optionally send data back // doneCallback(undefined, data); doneCallback(); } else { doneCallback(new Error("No DOM node found with id " + data.id)); } } ); virtDOM.render(virt.createView(HelloWorld), document.getElementById("app"));

Web Worker Example

When using a WebWorker the view processing is handled in the worker while the main thread only responses to render calls and updates the DOM.

Web Worker Script

var virt = require("@nathanfaucett/virt"), virtDOM = require("@nathanfaucett/virt-dom/src/worker/server"); virtDOM.render(virt.createView("p", "Hello, world!"));

Main thread

var virtDOM = require("@nathanfaucett/virt-dom/src/worker/client"); virtDOM.createRenderer( "path-to-worker-script.js", document.getElementById("app") );

WebSocket Example

When using WebSockets the main thread only responses to render calls and updates the DOM.

Server

var virt = require("@nathanfaucett/virt"), virtDOM = require("@nathanfaucett/virt-dom/src/websocket/server"), socket_io = require("socket.io"); var io = socket_io(), root = null; io.on("connection", function(socket) { virtDOM.render( virt.createView(virt.createView("p", "Hello, world!")), socket, function attachMessage(socket, callback) { socket.on("client-message", callback); }, function sendMessage(socket, data) { socket.emit("server-message", data); } ); }); console.log("listening on port 9999"); io.listen(9999);

Client

var io = require("socket.io-client"), virtDOM = require("@nathanfaucett/virt-dom/src/websocket/client"); var socket = io("localhost:9999"); socket.on("connect", function onConnect() { virtDOM.createRenderer( document.getElementById("app"), socket, function attachMessage(socket, callback) { socket.on("server-message", callback); }, function sendMessage(socket, data) { socket.emit("client-message", data); } ); }); socket.on("error", function(error) { console.log(error); });