htmlefet
v1.0.1
Published
Minimalist, non-intrusive one way binding html library
Downloads
1
Maintainers
Readme
HTMLefet
HTMLefet helps you bind data to html in a fast, robust way - using web standards and no more!
(no build step required - looking at you, lit-html)
Basic usage:
<script type="module">
import {efet} from "https://cdn.jsdelivr.net/npm/htmlefet/htmlefet.js"
window.state = {
name: "Inigo Montoystory",
color: "red"
};
// Binding the above object to an html template
let boundElement = eval(efet())(state, () => `
<div>
My name is <span style="color: ${state.color}">
${state.name}
</span>
</div>
`);
// boundElement is a regular html element!
document.body.appendChild(boundElement);
// modifying the state
state.name = "John Cena!!!";
setInterval(() => state.color = state.color === "blue" ? "red" : "blue", 300);
</script>
Play with it live: https://jsfiddle.net/8k1rvq6a/2/
In the above example, boundElement
is a regular DOM element. The only
thing that sets it apart is that when a property of state
changes,
the corresponding expression in the template will be re-evaluated and updated
in the element's DOM.
To get a feel for it, you can open the devtools and play with the state
object!
All of HTML, Bound
HTMLefet is straightforward - it's just html with js chunks inside. you don't have to learn how to use it. If your knowledge of js and html is a hand, HTMLefet is a well-fitting work glove.
Expressions
<div>my age will be ${state.age + 1} some day</div>
Events
<button onclick="${() => state.clicks += 1}">
click me baby ${state.clicks} more time
</button>
CSS
<style>
#thing {
color: ${state.color};
}
</style>
<div id="thing">colorful things</div>
You could write a css line (color: red;
), or even a whole rule.
Attributes
<input placeholder=${state.placeholder}/>
<div ${state.hidden ? "hidden" : ""}></div>
Nested
let boundElement = eval(efet())(state, () => `
<div>
${state.amAlive ? "yes" : eval(efet())(innerState, () => `
<span style="color: ${innerState.deathColor}">NO</span>
`)}
</div>
`);
Notice how the inner template uses a different state object: innerState
.
Loops
import {efet} from "https://cdn.jsdelivr.net/npm/htmlefet/htmlefet.js"
window.state = {
friends: [{
name: "dave",
isNice: true
}, {
name: "Mojojojo",
isNice: false
}, {
name: "harambe",
isNice: true
}]
};
let boundElement = eval(efet())(state, () => `
<div>
${state.friends.map(friend => eval(efet())(friend, () => `
<div style="color: ${friend.isNice ? "green" : "red"};">
${friend.name}
</div>
`))}
</div>
`);
document.body.appendChild(boundElement);
state.friends[0].isNice = false; // Boom
WTF The Fuck? We returned an array of bound elements, each of which is bound to a
different friend
. When we changed the isNice
ness of the first friend, its
bound element changed automatically.
keyed logic coming soon...
Web Components
No web rendering library is complete without a showoff of it's intended usage, while comparing it to other frameworks and stating why it's better!
...Coming Soon...
But why?
You're probably thinking "another web rendering library, more garbage, grate success". There are dozens of great libraries claiming to do the same, written by pretty smart people. so what sets HTMLefet apart?
Expression Hooks
HTMLefet maintains two important mappings in the background:
- properties to expression (
state.age
is linked to the expression${state.age / 2 + 7}
) - expressions to DOM Nodes (
${state.age / 2 + 7}
is linked to the div<div>${state.age / 2 + 7}</div>
)
When a property is changed (state.age += 1
), it's corresponding
expression is re-evaluated, and the result goes into the DOM Node.
It sounds simple, but it has a great advantage over other rendering libs: changes to the state follow with the minimum amount of reactions to make the DOM change.
Lets compare that to React
React claimed to be pretty fast because it took the slowest operation in the web and minimized it: changing the DOM. React keeps a copy of the DOM (called virtual dom), and whenever a rerender is queued, React compares the virtual DOM to the actual one, and changes the diffs.
But there's a problem. Imagine building a component that contains a huge list of
all the words, ever. You'd think that you only have to pay once, performance
wise: when rendering the list to the DOM. But it's not the case, because
whenever you call setState
without changing the list, the whole list is
still going to be compared to the actual DOM, unless you move that to another
component, forcing you to create lots of small and coupled components.
The comparison is not as heavy as actually replacing the DOM, but it's still very heavy when there's lots of stuff on the virtual DOM to compare.
That's one aspect where HTMLefet wins: when some property changes, instead of comparing the whole component, HTMLefet knows exactly what element to change because it holds a reference to it.
Level up: Lets compare to lit-html
TODO: Make sure im not bullshitting about how lit-html works...
Lit-html is the inspiration for this project (alongside lighterhtml). they keep it simple: no binding, user decides when to render. each rendering, the template is evaluated with all the expressions inside it, and puts them inside the DOM with the minimum amount of DOM work possible.
The catch: imagine a website showing two numbers: PI and E, but it calculates them on page load. on the fly
Disclaimer
All of what I said about the performance being good is a speculation, maybe i'm completely wrong - i havent run tests yet, soon i'll update with benchmark results.