WebReflection / lighterhtml

The hyperHTML strength & experience without its complexity 🎉
https://medium.com/@WebReflection/lit-html-vs-hyperhtml-vs-lighterhtml-c084abfe1285
ISC License
735 stars 20 forks source link

Returning DocumentFragment instead of HTML #25

Closed davidmerrique closed 5 years ago

davidmerrique commented 5 years ago

Hi, I noticed that lighterhtml returns a DocumentFragment instead of a DOM node like hyperHTML.

Is there a way to achieve similar behavior to hyperHTML? I like that behavior.

const hyper = hyperHTML.wire()`<div>Hyper</div>`;

console.log(hyper); // <div>

const lighter = lighterhtml.html`<div>Lighter</div>`;

console.log(lighter); // DocumentFragment [ div ]

Actually, as I was typing this issue I thought of something that works:

const lighter = lighterhtml.html.for({})`<div>Lighter</div>`;

console.log(lighter); // <div>

Is this that best way to achieve similar behavior? (Sorry, the documentation wasn't clear to me at first)

Thank you for these tools!

WebReflection commented 5 years ago

If you don't use a render(where, () => html...) you have an utility that does two things:

the html.for(ref[, id]) is the same as hyperHTML.wire(...) but if you don't have a render you should be just fine with the fragment.

The fragment is mandatory because you might do:

html`<p>1</p><p>2</p>`

there's no way to represent those two <P> without a fragment, and using a DIV, or any other wrap, won't work 'cause nodes might be contextual, example <TD>1</TD><TD>2</TD> and putting these inside a DIV would break.

davidmerrique commented 5 years ago

@WebReflection Got it, so using html.for({}), with an empty object as the ref, for one-off elements is perfectly fine? (as long as I don't try to render elements without a proper wrapping element)

I often want to create a one-off element, append it to the DOM, but keep a reference to it. And I can't do that with a DocumentFragment because the DocumentFragment is emptied after appending.

// This is essentially equivalent for my purposes, right?
const lighter = () => html.for({})`<div>Perfect</div>`;
const hyper = () => wire()`<div>Perfect</div>`;

Thank you

WebReflection commented 5 years ago

@davidmerrique if you have always one node just const html = (...args) => lighterhtml.html(...args).childNodes[0]; and call it a day. The html.for({}) doesn't grant a node, it's the same if you have multiple nodes without a single wrapper, it has to return a fragment, so that abusing the WeakMap won't make much sense.

WebReflection commented 5 years ago
// for one off operations
const html = (...args) => lighterhtml.html(...args).childNodes[0];

bear in mind if you use render in the wild that call won't do what you expect it to do.