@hoge1e3/dom-updater
v1.0.1
Published
A DOM tree updater that efficiently updates one HTML element tree (`dst`) to match another (`src`), with hooks to customize update behavior.
Readme
@hoge1e3/dom-updater
A DOM tree updater that efficiently updates one HTML element tree (dst) to match another (src), with hooks to customize update behavior.
Installation
npm install @hoge1e3/dom-updaterUsage
import { updater } from "@hoge1e3/dom-updater";
const domUpdater = updater({
// Optional hooks
});
domUpdater.update(destinationElement, sourceElement);API
updater(opt: Options): { update(dst: HTMLElement, src: HTMLElement): void }
Creates an updater instance with the given options. Returns an object with an update method to perform the DOM update.
Parameters
opt(optional): AnOptionsobject to customize update behavior.
Returns
An object with:
update(dst, src): Updatesdst(destination DOM) to matchsrc(source DOM).
Options (Type)
| Property | Type | Description |
|-----------------|----------------------------------------------|-------------|
| findUpdatable | (src: Node) => ChildNode \| null | Custom logic to locate an updatable node from rendered document corresponding to src. Default is "find the node from rendered document having same id of src". |
| isUpdatable | (dst: Node, src: Node) => boolean | Determines if a pair of nodes can be updated in-place. If dst=findUpdatable(src), it must be isUpdatable(dst, src), Default is either "Both dst and src have same id". "They have no id and have same tag name", or "Both of them are text nodes". |
| isSkippable | (dst: Node, src: Node) => boolean | Determines if the update for a node can be skipped. Default is "having same id and same value of attribute whose name is specified by attr_version option". |
| attr_version | string | Attribute used to determine if nodes can skip updates (defaults to "data-version"). |
| props | (node: Node) => string[] | List of properties to synchronize (Default: value and checked). |
How "updating" works
update(dst, src) works as:
- Shallow Update: Node attributes and properties are updated first.
- Recursive update: Child nodes are updated recursively:
- Call
isUpdatableondstandsrcsubnodes in that order to check if they are updatable. - If not, call
findUpdatablepassingsrcsubnode to find updatable nodes. - If an updatable node is found in
dst:- If necessary, reorder the updatable nodes in the order of
src. - If
isSkippableis called and the result is true, skip updating the versioned element. - If not skippable, do a recursive Recursive Update.
- If necessary, reorder the updatable nodes in the order of
- If no updateable node is found, insert a subnode of the
srcnode intodst.
- Call
- Delete Unused Nodes: Nodes in
dstthat were not updated in step 2 are unused, and they are deleted.
Example
const dst = document.getElementById("app")!;
const src = document.createElement("div");
src.innerHTML = `
<div id="foo" data-version="1">Updated Content</div>
`;
const domUpdater = updater({
attr_version: "data-version",
});
domUpdater.update(dst, src);Notes
- Text nodes are updated based on
textContent. - Attribute differences are synced.
- DOM order is preserved, with optimizations for minimal DOM operations.
- Unused nodes are removed after update.
Future works
- In this version, event listeners are not updated (event listeners are retained as they were when first inserted).
- In the near future, we plan to allow event listeners to be updated as well, but there will be restrictions on how event listeners can be registered (we will design this assuming @hoge1e3/dom is used)
