◆ live ディレクティブが追加された
◆ input の更新が自然にできるようになった

まちにまった lit-html の 1.2.0 がリリースされました!

機能追加はいくつかありますが重要なのは live ディレクティブです

lit-html では前回の render 時の値が内部に残っていて それと比較することで変更が必要かを判断します
DOM プロパティにアクセスしなくていいので効率的なのですが input などは画面で値を変更できるので内部で持ってる値と画面の表示(コンポーネントの値)が異なることがあります

これが困る部分でこのブログでも何度か記事に書いてます
最近だとこれとか
hyperhtml / lit-html で入力制限しようとすると

この問題は類似ライブラリの hyperhtml でも起きます

対処方法にはこういうことをしてました

lit-html で form の更新問題に対処する裏技?
lit-html でプロパティを強制更新する

これが標準機能でできるようになりました
それが live ディレクティブです

実装の経緯とか書かれた issue / PR はこれです

https://github.com/Polymer/lit-html/issues/877
https://github.com/Polymer/lit-html/pull/1057

つかってみる

さっそく使ってみます
使い方は ${} の中に値を入れるときに live() 関数を通すだけです

<script type="module">
import { html, render } from "https://unpkg.com/lit-html?module"
import { live } from "https://unpkg.com/lit-html/directives/live.js?module"

const values = {
text1: "",
text2: "",
}

const onInput = eve => {
values[eve.target.name] = eve.target.value.replace(/[^a-z]/g, "")
update()
}

const update = () => {
render(
html`
<h1>Input [a-z] only</h1>
<div>
<h2>Normal</h2>
<input name="text1" @input=${onInput} .value=${values.text1}>
<p>${values.text1}</p>
</div>
<div>
<h2>Live directive</h2>
<input name="text2" @input=${onInput} .value=${live(values.text2)}>
<p>${values.text2}</p>
</div>
`,
document.getElementById("root")
)
}

update()
</script>

<div id="root"></div>

上の Normal の方は live を使わず 下の Live directive の方では live を使ってます
どちらも小文字のアルファベット a ~ z しか入力できない制限をしています
内部で保持している値は input の直下にも表示されます

Normal の方では入力できない文字を打っても表示されて有効な文字を打って初めて入力できない文字が消えます
input に大文字や数字が出ているときに input 直下のテキストにはそれらは含まれません
Live directive の方は入力不可な文字を打っても何も表示されません

その他追加機能

他にも unsafeSVG ディレクティブと templateContent ディレクティブも追加されています

unsafeSVG

unsafeSVG は unsafeHTML があるので それの SVG 版のようです
通常では埋め込む Node は TextNode のみですが HTML を埋め込みたいときもあってそのための unsafeHTML です
それと同じことが SVG の中でもできるようです

利用シーンは HTML と一緒です
SVG は使ったこと無いので HTML で説明すると

リテラルならわざわざディレクティブを使わなくても

html`
<h1>
AAA
${html`<span class="a">aa</span>`}
</h1>
`

のようにテンプレートを作れば埋め込めます

しかし埋め込む HTML 文字列がユーザ入力や外部から取得するものでリテラルとしてコードに書いておけない場合もあります
その時に unsafe ディレクティブが使えます

const html_str = `<span class="a">aa</span>`
html`
<h1>
AAA
${unsafeHTML(html_str)}
</h1>
`

html はタグ関数なので

html(["<div>aaa</div>"])

と書いても良さそうですけどね

templateContent

これは template タグを指定すると その content にある DocumentFragment を埋め込んでくれるものです

const tpl = document.querySelector("template")

html`
<div>
${templateContent(tpl)}
</div>
`

すでに template タグを使っていてそれをあちこちにコピーして埋め込むなら使えますが わざわざ template タグを使わずに html タグ関数でテンプレートを書けばいいのであまり使うシーンが思いあたりません
template タグにすると ${} を使って埋め込む可変部分が作れませんし

1.2.1

書いてるうちに 1.2.1 が出ていましたが TypeScript 関連の修正で特に関係ないものでした