LoginSignup
3
6

More than 5 years have passed since last update.

lit-htmlでHello World!, FizzBuzz!

Last updated at Posted at 2018-11-12

lit-html
Polymerの新しい描画エンジンが 次世代HTMLテンプレートライブラリ と謳う lit-html になっているので勉強してみました。

lit-htmlとは

  • サイズが小さく高速 → JSベンチマーク
  • VirtualDOMを使わない
  • 2-way(双方向)bindingじゃない
  • HTML in JSで文字列テンプレートの中にJSを埋め込む
  • htmlタグリテラル関数でテンプレートをつくり、render()で描画。directive()でヘルパー関数をつくる
  • WebコンポーネントにするにはLitElementとして使うと便利

まあ、Chromeの開発チーム(ブラウザベンダ)がつくっているので、「DOMは遅いからVDOM」とか「JSの中にHTMLっぽいもの入れようぜ(JSX)」じゃなくてよいです。
ただ、2-way bindingに慣れていた身からするとReactぽい(?)描画や状態管理を勉強しなければならなさそうです、、、

どう使うか

<!doctype html>
<script type="module">
  import {html, render} from 'https://unpkg.com/lit-html?module'
  render(html`Hello World !`, document.body)
</script>

:globe_with_meridians: デモサイト (plunker)

type=module、、、? ES ModuleということはIE11で動かないのでしょうが、いくつか公開されているlit-htmlを使っているサンプルアプリがIE11で動いているので大丈夫なのでしょう。

htmlタグテンプレートリテラル

html`Hello World !`

ES2015/ES6で追加されたTagged Template literalが使用されていて、

const hello = name => html`Hello ${name}`
render(hello('World'), document.body)

こんな感じで値を入れて描画することができます。

const fizzBuzz = count => html`<ul>${[...Array(count)].map((_, i) => html`<li>${((i+1) % 3 == 0 ? 'Fizz' : '') + ((i+1) % 5 == 0 ? 'Buzz' : '') || (i+1)}</li>`)}</ul>`
render(fizzBuzz(20), document.body)

ループや条件式も入れることができます。

:globe_with_meridians: デモサイト (plunker)

renderレンダラー

render(html`hoge`, document.querySelector("#container"))

htmlで生成されたテンプレートはrender()で指定されたDOM以下に展開されますが、これだけならこちらの記事のように自分で拡張すれば済みそうです。
どうも作者の記事によると、内部で生成されたTemplateResultオブジェクトにPartsオブジェクトで目印をつくっておいてDOMをキャッシュしながら部分的に置換していくのが、Appleから出てきたTemplate Instantiationの仕様提案と親和性があってよい! らしい。。。

lit-html-parts

directiveプラグイン的な

基本htmlrender()しかないのでdirective()という関数で拡張させます。以下の例は標準で用意されているwhenrepeatです。
JSの評価式やループとの違いは上述のPartオブジェクトによって遅延評価されたり、DOMにキャッシュされるのが利点のようです。

import {html, render} from 'https://unpkg.com/lit-html?module'
import {when} from 'https://unpkg.com/lit-html/directives/when?module'
import {repeat} from 'https://unpkg.com/lit-html/directives/repeat?module' 

const fizzBuzz = count => html`<ul>
  ${repeat(
     [...Array(count)].map((_, i) => i + 1),
     i=>i,
     i => html`<li>${
      when(i % 3 == 0 && i % 5 == 0, ()=>'FizzBuzz', ()=>when(i % 3 == 0, ()=>'Fizz', ()=>when(i % 5 == 0, ()=>'Buzz', ()=>i))
      )}</li>`
  )}</ul>`

render(fizzBuzz(20), document.body)

:globe_with_meridians: デモサイト (plunker)

HTMLタグに対する属性(attribute)やスタイル、イベントリスナーへの登録などは書き方が特殊みたいですが、次回 LitElement を勉強する時に見てみたいと思ってます。

(続き :arrow_right: LitElement+TypeScriptでTodoリスト)

参考URL

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6