Cache a bel element. Makes rendering elements very fast™. Analogous to
React's .shouldComponentUpdate()
method, but only using native DOM methods.
- makes rendering elements very fast™
- widget API helps with creating stateful wrappers around 3rd party libs
- implemented in only a couple of lines
- only uses native DOM methods
Here we take a regular element, and cache it so re-renders are fast:
const cache = require('cache-element')
const html = require('bel')
const renderEl = cache(function (name, age) {
return html`
<p>Name is ${name} and age is ${age}</p>
`
})
let el = renderEl('Tubi', 12) // creates new element
let el = renderEl('Tubi', 12) // returns cached element (proxy)
let el = renderEl('Babs', 25) // creates new element
Here we take a widget (e.g. d3, gmaps) and wrap it so it return a DOM node once, and then only has to worry about managing its lifecycle:
const widget = require('cache-element/widget')
const html = require('bel')
const renderEl = widget(function (update) {
let name = null
let age = null
update(onupdate)
return html`
<p onload=${onload} onunload=${onunload}>
Name is ${name} and age is ${age}
</p>
`
function onupdate (newName, newAge) {
name = newName
age = newAge
}
function onload () {
console.log('added to DOM')
}
function onunload () {
name = null
age = null
console.log('removed from DOM')
}
})
let el = renderEl('Tubi', 12) // creates new element
let el = renderEl('Tubi', 12) // returns cached element (proxy)
let el = renderEl('Babs', 25) // returns cached element (proxy)
Cache an element.
Render a widget.
Render an element, passing it arbitrary arguments.
Make sure you're running a diffing engine that checks for .isSameNode()
, if
it doesn't you'll end up with super weird results because proxy nodes will
probably be rendered which is not what should happen. Probably make sure you're
using morphdom. Seriously.
It's a node that overloads Node.isSameNode()
to compare it to another node.
This is needed because a given DOM node can only exist in one DOM tree at the
time, so we need a way to reference mounted nodes in the tree without actually
using them. Hence the proxy pattern, and the recently added support for it in
certain diffing engines:
const html = require('bel')
const el1 = html`<div>pink is the best</div>`
const el2 = html`<div>blue is the best</div>`
// let's proxy el1
const proxy = html`<div></div>`
proxy.isSameNode = function (targetNode) {
return (targetNode === el1)
}
el1.isSameNode(el1) // true
el1.isSameNode(el2) // false
proxy.isSameNode(el1) // true
proxy.isSameNode(el2) // false
Morphdom is a diffing engine that diffs real DOM trees. It runs a series of checks between nodes to see if they should either be replaced, removed, updated or reordered. This is done using a series of property checks on the nodes.
Since v2.1.0 morphdom
also runs Node.isSameNode(otherNode)
. This
allows us to override the function and replace it with a custom function that
proxies an existing node. Check out the code to see how it works. The result is
that if every element in our tree uses cache-element
, only elements that have
changed will be recomputed and rerendered making things very fast.
cache
return a proxy node if the arguments were the same. If arguments change, it'll rerender and return a new node.widget
will always return a proxy node. It also listens for the node to be unmounted from the DOM so it can clean up internal references, making it more expensive to use.
$ npm install cache-element