diffHTML

v1.0.0

The easy-to-use Virtual DOM, built for the web!

API

The core diffHTML API was designed to be minimal and familiar if you've used browser DOM APIs such as innerHTML and addEventListener.

You can access any of the top-level API methods & properties by directly importing or deconstructing.

Using ES modules

import { innerHTML, VERSION, use } from 'diffhtml';
// or
import diff from 'diffhtml';

Using CommonJS

const { innerHTML, VERSION, use } = require('diffhtml');
// or
const diff = require('diffhtml');

Using browser globals

const { innerHTML, VERSION, use } = window.diff;
// or
const { diff } = window;


innerHTML (domNode, markup, options)

Replaces the contents of a DOM node with the passed in markup, but will only update changed content and structure. Works like the browser's innerHTML only changing the element's children, but not the containing element. If you want to control the entire tag, use outerHTML.

Arguments

Name Description
domNode The root DOM Node to change the child contents of, but not the element itself.
markup New markup to replace into the domNode.
options
  • - tasks: An array of tasks to run. Can swap these out completely to run custom logic instead.

Examples


outerHTML (domNode, markup, options)

Replaces the contents of a DOM node with the passed in markup, only updates what has changed. Additionally updates the attributes of the parent. If the element you're modifying has a parent, you may also change the element type, but this isn't really recommended.

Example:

outerHTML(document.body, '<body>Hello world</body>');

Arguments

Name Description
domNode A DOM Node to change.
markup New markup to replace the entire domNode with.
options
  • - tasks: An array of tasks to run. Can swap these out completely to run custom logic instead.


html (markup)

A tagged template function that parses HTML and creates VTree's under-the-hood. Can also be used like a normal function. Effectively creates the manual createTree(nodeName, attributes, children) calls automatically by parsing the HTML. You are allowed to "interpolate" or mix dynamic values with the HTML string content. This is useful when working with Web Components, DOM events,

When you pass a single element and provide newlines and whitespace before and after it, like the example below, it will be automatically trimmed. If you provide multiple elements, the whitespace becomes

A simple example of its usage along with interpolation.

html`
  <body>
    <center style=${{ fontSize: '11px' }}>Hello world</center>
  </body>
`;

Will basically convert to:

createTree('body', null, [
  createTree('center', { style: { fontSize: '11px' } }, ['Hello world']),
]);

To see how to run this example yourself see the Examples section below.

Arguments

The two required inputs are a reference element and new element to compare. Although "element" is used, the actual input can be of various input types all representing an element (or many elements).


use (middlewareFunction or middlewareObject)

Can be used to mount pre-existing middleware or you can write your own. Middleware are effectively hooks that execute in various areas of the reconciler during a render call such as innerHTML or outerHTML.

A function is useful when you want to follow the transactions (which are started and run a series of tasks), and passing an object can be cleaner when you want to modify the Virtual Tree or automatically add properties.

Arguments

Name Description
middlewareFunction Use this when you want total control over the task flow. Return inner functions to delve deeper into the flow. Any of the middleware object properties may be attached the function and used together.
middlewareObject Use this when you don't care about the transaction start/stop, and want a cleaner way to monitor the VTree lifecycle.

- createTreeHook

- syncTreeHook

- releaseHook

Examples

Logging the start of a render transaction

function someTask(transaction) {
  console.log('Start of render transaction:', transaction);
}

use(someTask);

Logging the end of a render transaction

function someTask(transaction) {
  console.log('Start of render transaction:', transaction);

  return () => {
    console.log('End of render transaction scheduled');

    // Must wait until all transitions complete to know for sure that the
    // render action has completed.
    transaction.onceEnded(() => {
      console.log('End of render transaction completed');
    });
  };
}

use(someTask);


addTransitionState (stateName, callback)

Replaces the contents of a DOM node with the passed in markup, only updates what has changed.

Example:

outerHTML(document.body, 'Hello world');

To see how to run this example yourself see the Examples section below.

Arguments

The two required inputs are a reference element and new element to compare. Although "element" is used, the actual input can be of various input types all representing an element (or many elements).


removeTransitionState (stateName, callback)

Replaces the contents of a DOM node with the passed in markup, only updates what has changed.

Example:

outerHTML(document.body, 'Hello world');

To see how to run this example yourself see the Examples section below.

Arguments

The two required inputs are a reference element and new element to compare. Although "element" is used, the actual input can be of various input types all representing an element (or many elements).


createTree (nodeName, attributes, childNodes)

Replaces the contents of a DOM node with the passed in markup, only updates what has changed.

Example:

outerHTML(document.body, 'Hello world');

To see how to run this example yourself see the Examples section below.

Arguments

The two required inputs are a reference element and new element to compare. Although "element" is used, the actual input can be of various input types all representing an element (or many elements).


release (domNode)

Use this method if you need to clean up memory allocations and anything else internal to diffHTML associated with your element. This is very useful for unit testing and general cleanup when you're done with an element. Applications will probably not use this if the app lives as long as the tab.

Arguments

Name Description
domNode The root DOM Node to release memory around

This method should fully release everything related to the rendering, but its possible an untested code path is hit, so you should track the internal memory allocations to verify that memory isn't causing a problem.

domNode

Reference element.

This argument is overloaded. Can be one of many types:


Internals

The internals are exposed for curious developers to write code against. Understanding these APIs will give you greater insight into how diffHTML works.

MiddlewareCache

An object that contains Sets of functions. You can hook into:

NodeCache

A Map that can be used to get access to the DOM Node associated to a VTree. This is comparable to findDOMNode in React. Basically if you encounter an object that the documentation says is a VTree and you want to convert to a DOM Node, you could write something like:

import { Internals } from 'diffhtml';

function findDOMNode(vTree) {
  return Internals.NodeCache.get(vTree);
}

findDOMNode(someVTree);

If it comes back as null or undefined then you should take that to mean that the VTree is no longer bound to an element in the DOM. You may also find that diffHTML has re-used the VTree you have saved, so calling NodeCache.get will yield an unexpected result. Therefore its recommended to call this method immediately if you need the DOM node and not save a VTree in between re-renders.

Transaction

A render transaction is scheduled whenever innerHTML or outerHTML are called. It is a subclass of a Transaction class that gives it a few methods: abort, end, onceEnded, and start. This instance is mutable and the properties will change by the internals. You should not modify the transaction directly unless you know what you're doing. Reading any property is considered the live source-of-truth and a safe operation.

There are a series of tasks that run when a transaction is created. Depending on the build flavor, full or runtime, you will get a different set of tasks. By default transactions run synchronously and you can observe a result immediately after running innerHTML or outerHTML.

If you use addTransitionState and return a Promise to delay rendering, this could cause multiple renders to stack up and then transactions will be asynchronous.

> schedule        # If another transaction is running, this will run after
> shouldUpdate    # If nothing has changed, abort early
> parseNewTree    # Full build only, will parse a passed in string of HTML
> reconcileTrees  # Align trees before diffing
> syncTrees       # Loop through and compare trees as efficiently as possible
> patchNode       # Apply chnages to the DOM
> endAsPromise    # If a transaction is delayed, resolve once complete

Transactions have a number of properties available to access:


VERSION

Property which indicates the current running version of diffHTML.

Example

console.log(VERSION);

Edit on GitHub