hydro-js
A lightweight (~1.7K compressed) reactive UI library via template literal tags.
Installation
$ npm install hydro.js
import { render, html } from 'hydro-js';
Akternatively you can use a CDN
<script type="module">
import { render, html } from "https://unpkg.com/hydro-js";
</script>
Examples
Concept
There are multiple things this library can do. The first thing is generating HTML from strings. This is mostly done by the Range Web API
. There are already ways to do that, like Element.insertAdjacentHTML()
, but this has some drawbacks, as it does not create some Table Elements, like <colgroup>
, <tbody>
, <tfoot>
, <thead>
and <tr>
. Furthermore, the html function deals with inline events, objects, {{ Mustache }} etc. Using this function will feel like writing JSX without a build step.
The render function is used for mounting and unmounting Elements to the DOM and for executing lifecycle hooks. Optionally, it can diff both HTML Trees and reuse Elements (optionally too).
The functions calls for render
and DOM Updates are queued and worked on during a browser's idle periods.
In order to make the DOM reactive, ES6 Proxy
objects are being used to map data against an array of DOM Elements. Whenever the setter is being called, the Proxy will check the mapping and update the DOM granularly.
Almost all intern maps are using WeakMaps with DOM Elements or Proxy object as keys and memory is cleared efficiently.
Documentation
html
args: string
returns: DocumentFragment | Element | Text
Takes a string and transforms it to HTML. Used for internal bookkeeping too.
render
args:
- new Element (
DocumentFragment | Element | Text
) - old Element (
Element | string
) - ? shouldschedule: boolean (default: true)
returns: function
that unmounts the new Element
Accepts the return value of html
and replaces it with the old Element. If old Element is a string, it will resolve it with querySelector
.
setGlobalSchedule
args: boolean
Will enable/disable the queue for render
and DOM Updates. Defaults to true
.
setReuseElements
args: boolean
Will enable/disable the reuse of Elements in the diffing Phase of render
. Defaults to true
.
setInsertDiffing
args: boolean
If enabled, it will insert the new Element to the DOM before diffing. This will asssure that reused Elements will not lose their state (e.g. <video>
in Chrome. Defaults to false
.
onRender
args:
function
- elem (
DocumentFragment | Element | Text
) - ...args for passed
function
Calls the passed in function
with ...args
, after the Element is being inserted by render
;
onCleanup
args:
function
- elem (
DocumentFragment | Element | Text
) - ...args for passed
function
Calls the passed in function
with ...args
, after the Element is being diffed out by render
or removed by unmount
;
reactive
args: value: any
returns: unique Proxy object
Returns a Proxy object that can be used in html
. The Proxy is a layer over a function that can set the value. If the argument is a function, then the argument of the passed in function will be provided as the current value for the Proxy.
Interally, the hydro Proxy is used and this reactive Proxy hides it's complexity.
observe
args:
ReturnType<typeof reactive>
function
Calls the function whenenver the value of reactive changes. This is only one layer deep but chaining properties returns a Proxy too.
getValue
args: ReturnType<typeof reactive>
Returns the value inside the the Proxy. getValue is needed because chaining properties returns a Proxy.
ternary
args:
- condition:
function | ReturnType<typeof reactive>
- trueVal:
any
- falseVal:
any
- ? proxy:
ReturnType<typeof reactive>
returns: ReturnType<typeof reactive>
In order to track a ternary, that is being used in a template literal, this function has to be used. The proxy parameter is optional if the first parameter is a Proxy. Otherwise, a function is being executed, whenever the Proxy value changes, which will update the DOM to either the trueVal or the falseVal
(it will also execute truVal/falseVal, if it is a function).
unset
args: ReturnType
Deletes the Proxy object. This is important to keep memory low.
hydro
The actual Proxy in the library. This cannot be used with getValue
, observe
, ternary
or unset
but it offers the same functionality in a different manner.
emit
args:
- event:
string
- data:
any
- who:
EventTarget
- options:
object
(default: { bubbles: true }
)
Emits an event from the EventTarget who. This event bubbles by default.
internals
An object with internal data / functions for testing or deeper dives for developers. This only includes a compare
function for DOM Elements by at the moment.
Roadmap
• Add GitHub Actions for Publishing
• Snowpack Starter Project with Prerendering
• Add Broadcast channel or alike to sync updates over multiple tabs
• Experiment with Code in Worker
• Experiment if the above code can be replaced by wasm
• Refactor some code parts, once WeakRef is supported in Safari