lit-html と htm+preact
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ シンプルなものだと同じコードで動く
◆ 互換性ない部分もあるけど頑張ればどっちでも動かせるものが作れそう
◆ 互換性ない部分もあるけど頑張ればどっちでも動かせるものが作れそう
似たように書けるなぁと思っていましたが エクスポートされる関数名も一緒だったので同じコードで動きました
上側が lit-html で下側が htm+preact です
違いは h1 の中のテキストとコンテナになる HTMLElement の id だけです
関数にまとめてしまってこれでも動きます
すでに見つけたものだけでもこれだけ違いがありました
htm では (P)React の createElement の第 2 引数で指定するものに合わせないといけません
hyperhtml のほうが近くなると思います
input みたいな終了タグなしで self closing でもないタグは HTML だと許可されてますが XML だと不正です
こういうのがあるとエラーになるかおかしな構造として扱われてしまいます
lit-html では HTML としてブラウザがパースするので HTML であれば問題なしです
タグ全体を条件分岐で出し分けることになります
htm の場合は (P)React で createElement の第 1 引数にコンポーネントを指定するように動的なものを設定できます
その場合の閉じタグは <//> です
lit-html ではこれは有効ですが htm の場合はアンエスケープされず そのまま < などがテキストとして表示されます
回避方法は ${} を使って文字列として HTML タグを入れることです
見つけた限りだと互換性はけっこう高めです
XML やエスケープのものは htm の書き方は lit-html でも有効なので この辺は htm で動く書き方してれば lit-html でも動きます
(P)React 風な使い方をすればコンポーネントを作るので タグ名に ${} を使うことになりますが lit-html のような使い方にしてコンポーネントを作らないならタグ名に ${} を使うことはほぼ無いです
属性名のところだけが難しいですが htm の bind のところでフックして lit-html の属性名を (P)React の属性名に置換するような処理を入れれば完全互換も夢じゃないかもしれません
そこまでして両方で動くコードを書くメリットはたぶん無いですけどね
<!doctype html>
<meta charset="utf-8" />
<style>
.red { color: red; }
.blue { color: blue; }
.green { color: green; }
</style>
<script type="module">
import { html, render } from "https://unpkg.com/lit-html"
const colors = ["red", "blue", "green"]
render(
html`
<h1>lit-html rendering</h1>
<p>${"abc".repeat(5)}</p>
<div>${
colors.map(e => html`<div class=${e}>${e}</div>`)
}</div>
`,
document.getElementById("lit-html-root")
)
</script>
<script type="module">
import { html, render } from "https://unpkg.com/htm/preact/standalone.module.js"
const colors = ["red", "blue", "green"]
render(
html`
<h1>htm-preact rendering</h1>
<p>${"abc".repeat(5)}</p>
<div>${
colors.map(e => html`<div class=${e}>${e}</div>`)
}</div>
`,
document.getElementById("htm-preact-root")
)
</script>
<div id="lit-html-root"></div>
<div id="htm-preact-root"></div>
上側が lit-html で下側が htm+preact です
違いは h1 の中のテキストとコンテナになる HTMLElement の id だけです
関数にまとめてしまってこれでも動きます
<!doctype html>
<meta charset="utf-8" />
<style>
.red { color: red; }
.blue { color: blue; }
.green { color: green; }
</style>
<script type="module">
import * as lithtml from "https://unpkg.com/lit-html"
import * as htmpreact from "https://unpkg.com/htm/preact/standalone.module.js"
const commonRender = (name, lib, container) => {
const { html, render } = lib
const colors = ["red", "blue", "green"]
render(
html`
<h1>${name} rendering</h1>
<p>${"abc".repeat(5)}</p>
<div>${
colors.map(e => html`<div class=${e}>${e}</div>`)
}</div>
`,
container
)
}
commonRender("lit-html", lithtml, document.getElementById("lit-html-root"))
commonRender("htm-preact", htmpreact, document.getElementById("htm-preact-root"))
</script>
<div id="lit-html-root"></div>
<div id="htm-preact-root"></div>
違い
シンプルなものだと同じコードでいいのですが 完全に一緒とはいかないですすでに見つけたものだけでもこれだけ違いがありました
属性名
lit-html では @ や . など記号を使ってプロパティやイベントリスナなどを表しますhtm では (P)React の createElement の第 2 引数で指定するものに合わせないといけません
hyperhtml のほうが近くなると思います
XML
htm は JSX と同じで XML で書かないといけませんinput みたいな終了タグなしで self closing でもないタグは HTML だと許可されてますが XML だと不正です
こういうのがあるとエラーになるかおかしな構造として扱われてしまいます
lit-html では HTML としてブラウザがパースするので HTML であれば問題なしです
タグ名
lit-html ではタグ名の部分に ${} を使うことはできませんタグ全体を条件分岐で出し分けることになります
htm の場合は (P)React で createElement の第 1 引数にコンポーネントを指定するように動的なものを設定できます
その場合の閉じタグは <//> です
エスケープ
HTML ではテキストとして HTML タグを書きたい場合は <div> のようにエスケープしますlit-html ではこれは有効ですが htm の場合はアンエスケープされず そのまま < などがテキストとして表示されます
回避方法は ${} を使って文字列として HTML タグを入れることです
html`<h1>${"<div>"}</h1>`
まとめ
htm はまだ使って数日なので 他にもまだ違いは色々あるかもしれません見つけた限りだと互換性はけっこう高めです
XML やエスケープのものは htm の書き方は lit-html でも有効なので この辺は htm で動く書き方してれば lit-html でも動きます
(P)React 風な使い方をすればコンポーネントを作るので タグ名に ${} を使うことになりますが lit-html のような使い方にしてコンポーネントを作らないならタグ名に ${} を使うことはほぼ無いです
属性名のところだけが難しいですが htm の bind のところでフックして lit-html の属性名を (P)React の属性名に置換するような処理を入れれば完全互換も夢じゃないかもしれません
そこまでして両方で動くコードを書くメリットはたぶん無いですけどね