どうも、ヒロと申します。フロントエンドマンです。
Polymer Advent Calendar 2017 7日目の担当です!
投稿が遅れてしまいすみません、、、汗
今回はlit-htmlの紹介をしたいと思います。
lit-htmlとはPolymerチーム が開発しているView用のライブラリです。
非常に軽量でシンプルなAPIのみ提供しているライブラリです。まだ絶賛開発中なのでプロダクション利用には向いていないと思いますが、今回はこのライブラリについて説明します。
いきなりですが、今回このようなサンプルを用意しました。
はい、TODO Exampleです。
コードはこちらにあります。
では早速コードの説明に入る前に簡単にlit-htmlの使い方の説明!
lit-htmlの主要な機能は二つ、
- html()
- render()
の二つです。公式のサンプルそのままですが、
import {html, render} from 'lit-html';
// html()関数でレンダリングするDOMの内容を定義します。
const helloTemplate = (name) => html`<div>Hello ${name}!</div>`;
// 引数に渡したパラメーターはそのまま${}
// 内に渡ります。またレンダリングする時はrender() 関数の第一引数にhtml()で定義した
// 関数と第二引数にDOMを指定します。
render(helloTemplate('Steve'), document.body);
// 引数を変えて再度レンダリングすると引数の内容だけ再レンダリングされます。
render(helloTemplate('Kevin'), document.body);
ではここからサンプルのコードをざっくり解説したいと思います!
主なフォルダ構成
├── src
│ ├── index.ejs
│ └── js
│ ├── Todo.js
│ ├── components
│ │ ├── Footer.js
│ │ ├── FooterItem.js
│ │ ├── Header.js
│ │ ├── MainField.js
│ │ └── TodoItem.js
│ ├── containers
│ │ └── App.js
│ ├── domain
│ │ ├── allCheck.js
│ │ ├── check.js
│ │ ├── count.js
│ │ ├── deleteChild.js
│ │ └── filterChange.js
│ ├── index.js
│ ├── mock
│ │ ├── defaultFilter.js
│ │ └── mock.js
│ └── style.css
Todo.js
基本的な処理の内容を記述しているファイル
components
コンポーネント用のディレクトリ
containers
TODO周りの全体のUI用のディレクトリ
domain
components内のコンポーネント内で主にon-click
内で発火する関数用のディレクトリ
index.js
custom-elementsのdefineをしているファイル
mock
初期状態のTodoデータと初期状態のフィルターのデータ等が記述されているファイルのあるディレクトリ
style.css
style.css
設計内容
主な処理は Todo.js
内に記述しているので、その中身を説明します。
主に static get observedAttributes()
内でobserveしている値によって class
内のメソッドを発火しています。
...
static get observedAttributes() {
return ['update', 'delete', 'change', 'filter', 'all-check', 'init'];
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'change':
return this.change(newValue);
case 'update':
return this.update();
case 'delete':
return this.delete(newValue);
case 'filter':
return this.filterState(newValue);
case 'all-check':
return this.allCheckState();
case 'init':
return this.init(newValue);
}
}
...
また this.generate(todoのデータが入っている配列, filterのデータが入っている配列)
という形で形で使用していて、TODOのデータを追加する時、削除する時等、何か変更が入る度にこのmethodを呼び出しています。
TODOのデータに関して this.state
内に値を保持しており、 this.setState(stateをアップデートobject)
関数を発火することでのみ内容を変えています。
また初期ロード時に、session storageに値があればその内容をレンダリングするという this.read()
メソッドと、 何かしらの変更があったら現在の状態を保存する this.store()
というメソッドがあります。
this.read()
に関しては初期ロード時にのみ発火し、 this.store()
に関しては各メソッドの最後の処理に発火し、状態を保存しています。
実装していて困った点
lit-html
ではコンポーネント内で onclick
を発火させる時に on-click
と記述して使用します。 またコンポーネント内の on-click
で埋め込んだ関数を発火すると this.setAttribute()
でcustom-elementsの親階層のdata属性を変更して、その後に static get observedAttributes()
でobserveしているdata属性に応じて attributeChangedCallback()
内で処理をしています。ただ、 this.querySelector()
で親のcustom-elementを探してそのdata属性を変更するというのは綺麗な実装ではありません。
この辺りをもう少し工夫したかったなと思いました(時間があまりなかったというのはありますが、、、)
また lit-html
内の APIが途中で変わったり、変更されたりしていたので、本当に絶賛実装中なんだなと感じました。特に lit-extended.ts
周りが特にですね。
というのも最初 on-click
でコンポーネントに onclick
イベントを埋め込むには node_modules
直下から以下のように
./node_modules/lit-html/lib/lit-extended.ts
のように直接読み込まないと使用できませんでした。 ただバージョンアップに伴い、直接 on-click
を書いても onclick
イベントを発火出来るようになったのかもしれません。
終わりに
lit-html
の紹介というよりかはサンプルを作ったのでその紹介みたいな感じになってしまいました。次回はちゃんとAPIの紹介をして行ければと思います。
個人的な意見ですが、 lit-html
は今後どんどん改修、機能追加されて行くと思いますし、polymer 3.0と上手く組み合わせいけるような感じになるんじゃないかなーと思います。実際どうなんでしょう?引き続き動向を伺いつつ、深く理解していきたい次第です。
明日は@howkingさんの
Polymer & Firebase でサイト更新したらプッシュ通知です!
Polymer Advent Calendar 2017
6日目 未経験者が触るPolymer 3.0 preview @usagi-f
8日目 Polymer & Firebase でサイト更新したらプッシュ通知 @howking