Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/DylanPiercey/set-dom

📑 Lightweight dom diffing with plain old html.
https://github.com/DylanPiercey/set-dom

Last synced: 18 days ago
JSON representation

📑 Lightweight dom diffing with plain old html.

Awesome Lists containing this project

README

        




Set-DOM Logo




API stability



Standard



NPM version



Build status



Test Coverage



File size



Downloads



Gitter Chat


Browser Matrix

A lightweight library to update DOM and persist state.
IE: React diffing with html instead of JSX (bring your own templating language).

# Why
JSX is great but there are so many other nice alternatives.
React is great but it's clunky and opinionated.

This is inspired by [diffhtml](https://github.com/tbranyen/diffhtml), [morphdom](https://github.com/patrick-steele-idem/morphdom) and my knowledge from [tusk](https://github.com/DylanPiercey/tusk). I set out to create a no nonsense "dom to dom" diffing algorithm that was fast and compact.

### Features
* ~800 bytes min/gzip.
* Minimal API.
* Keyed html elements (`data-key` or `id` to shuffle around nodes).
* Use whatever you want to generate html.

# Installation

#### Npm
```console
npm install set-dom
```

#### [Download](https://raw.githubusercontent.com/DylanPiercey/set-dom/master/dist/set-dom.js)
```html

define(['set-dom'], function (setDOM) {...}); // AMD
window.setDOM; // Global set-dom if no module system in place.

```

# Example

```javascript
const setDOM = require("set-dom");

// We will use handlebars for our example.
const hbs = require("handlebars");
const homePage = hbs.compile(`


My App




{{title}}
{{#each frameworks}}

{{name}} is pretty cool.

{{/each}}




`);

// You can replace the entire page with your new html (only updates changed elements).
setDOM(document, homePage({
title: "Hello World.",
frameworks: [
{ name: "React" },
{ name: "Angular" },
{ name: "Ember" },
{ name: "Backbone" },
{ name: "Everything" }
]
}));

// Or update individual elements.
setDOM(myElement, myHTML);
```

# API
+ **setDOM(HTMLEntity, html|HTMLEntity)** : Updates existing DOM to new DOM in as few operations as possible.

---

# Advanced Tips

## Keys
Just like React (although slightly different) `set-dom` supports keyed nodes.
To help the diffing algorithm reposition your elements be sure to provide a `data-key` or `id` attribute on nodes inside a map. This is optional but key for performance when re-ordering/modifying lists.

Another key difference from React is that `set-dom` simply can't tell when you are rendering an entirely different component. As such it is good practice to use `data-key` when you know that most of the html will be discarded (like when rendering an entirely different page) to skip the diffing process entirely.

## Checksum
Another trick to help set-dom with it's diffing algorithm is to provide a `data-checksum` attribute. This attribute will only do any diff on an element (and it's children) if the checksum changes allowing you to skip diffing entire trees of the document. Check out [hash-sum](https://github.com/bevacqua/hash-sum) for a quick and simple checksum that you can use in your templates. Simply hash the state/data for your view and set-dom will only do any changes to the document once the hash has changed.

## Ignored
Sometimes it is required to simply escape the whole diffing paradigm and do all of the manual dom work yourself. With `set-dom` it is easy to include these types of elements in the page using a special `data-ignore` attribute.

Any elements that have a `data-ignore` will only be diffed when the `data-ignore` attribute is removed. The only thing `set-dom` will do for you in this case is automatically add and remove the element.

## Event delegation
Unlike React, set-dom does not provide a way for you to add event listeners to your elements. Fortunately there is a simple approach that enables this that you have probably used before (aka jquery), [event delegation](https://davidwalsh.name/event-delegate). Check out something like [component-delegate](https://github.com/component/delegate) for a lightweight library that does this for you. Or if you are using [Rill](https://github.com/rill-js/rill) checkout [@rill/delegate](https://github.com/rill-js/delegate).

## Mounting and Dismounting.
Often you need the ability to intercept when a component is inserted or removed from the DOM.
Keyed elements (those with `data-key` or `id` attributes) will automatically emit custom `mount` and `dismount` events when they are inserted and removed from the DOM.

You can use these events to handle setup and teardown of complex components along side event delegation.

## Overrides
You can also easily override the attributes used for both *keying* and *ignoring* by manually updating the `KEY`, `CHECKSUM` and `IGNORE` properties of `set-dom` like so.

```js
// Change 'data-key' to 'data-my-key'
setDOM.KEY = 'data-my-key'

// Change 'data-checksum' to 'data-my-checksum'
setDOM.CHECKSUM = 'data-my-checksum'

// Change 'data-ignore' to 'data-my-ignore'
setDOM.IGNORE = 'data-my-ignore'
```

### Benchmarks
Benchmarks are available on the [vdom-benchmark](https://vdom-benchmark.github.io/vdom-benchmark/) website.

### Contributions

* Use `npm test` to run tests.

Please feel free to create a PR!