Snowpackのapp-template-lit-elementでかんたんWeb Compoments作成
UI開発者 古川Snowpackはフロントエンド開発環境を構築するためのビルドツールです。
Snowpackには、単体でCreate Snowpack App(CSA)と呼ばれる各開発環境のスターターセットが用意されています。今回はCreate Snowpack Appのひとつであるapp-template-lit-elementを利用して、かんたんなWeb Componentsを作成する手順を紹介します。
app-template-lit-elementのインストール
app-template-lit-elementをインストールするには、まず以下のコマンドを任意のディレクトリで実行します。
npx create-snowpack-app [dirname] --template @snowpack/app-template-lit-element
インストールが完了したら、任意のディレクトリに移動して以下のコマンドのようにnpm start
を実行してください。
cd [dirname]
npm start
http://localhost:8080
にアクセスし、ブラウザで次のキャプチャのように表示されたら環境構築は成功です。
ボタンのコンポーネントを作成
以下のGifアニメーションのように、ON/OFFを切り替えるトグルボタンを作成してみます。
カスタムエレメントを定義
まずはコンポーネント用のファイルを作成します。
app-template-lit-elementで生成したテンプレートでは、コンポーネントとなるファイルはすべてsrc/
ディレクトリ配下に格納されています。
そこで、トグルボタン用のファイルをsrc/Components/ToggleButton.js
という名前で作成し、以下のようにコードを記述します。
import { customElement, LitElement, html } from 'lit-element';
@customElement('toggle-button')
export class ToggleButton extends LitElement {
render() {
return html`
<button class="c-button">ボタン</button>
`;
}
}
はじめに、コンポーネントに必要なLitElementライブラリを読み込みます。app-template-lit-elementではWeb Componentsの生成にLitElementを使用しています。LitElementはWebComponentsを生成するためのクラスライブラリで、内部的にはlit-htmlを利用しています。
続いてLitElementの@customElementデコレーターでカスタムエレメントを定義します。今回は<toggle-button>
というコンポーネントを定義してみましょう。
デコレーターは本来まだネイティブのJavaScriptでは使えませんが、Babelのプラグインを使って利用が可能です。app-template-lit-elementでは、あらかじめデコレーターを利用する設定が完了しています。
カスタムエレメントの定義の次は、コンポーネントのShadow DOMテンプレートを定義します。テンプレートを定義するには、LitElementクラスのrender()
関数を実装します。lit-elementのhtml
関数をタグ付きテンプレートリテラルで呼び出し、render()
関数がその結果を返すようにします。
// ...
render() {
return html`
<button class="c-button">ボタン</button>
`;
}
// ...
ここまで記述が完了したら、画面の要素を表示している./src/app-root.js
で、作成したコンポーネントをimport
文で読み込みます。次に./src/app-root.js
のrender()
関数内にさきほど定義した<toggle-button>
を記述します。
import { customElement, property, LitElement, html, css } from 'lit-element';
import './Components/ToggleButton'; // コンポーネントの読み込み
// (中略)
// ...
render() {
return html`
<div class="wrapper">
<h1>LitElement + Snowpack</h1>
<p>Edit <code>src/app-root.js</code> and save to reload.</p>
<toggle-button></toggle-button>
<a
class="link"
href="https://lit-element.polymer-project.org/"
target="_blank"
rel="noopener noreferrer"
> ${this.message}</a>
</div>
`;
}
// ...
ここまでのコードをブラウザで実行すると以下のキャプチャのようになります。
プロパティを定義
クリックイベントをトリガーにボタンのスタイルとテキストを切り替えたいため、@propertyデコレーターでデータバインディング用にpressed
という名前のプロパティを定義したいと思います。
まずはじめにlit-elementライブラリから@propertyデコレーターを読み込み、以下のコードのように記述します。
import { customElement, property, LitElement, html } from 'lit-element';
@customElement('toggle-button')
export class ToggleButton extends LitElement {
@property({
type: Boolean,
reflect: true
})
pressed = false;
// (省略)...
}
LitElementでは属性の振る舞いなどをカスタマイズすることができ、その内容はオプションで設定できます。今回ポイントとなるのはreflectという設定です。このreflect
はプロパティの変更を、カスタム要素に属性として反映させることができます。今回はプロパティをBooleanで設定しているため、true
のときは属性が付与され、false
のときは属性が削除されます。このように、LitElementではプロパティ自体の振る舞いをカスタマイズすることが可能です。
続いて、定義したpressed
プロパティを利用して、ボタンの文言を切り替える式をカスタム要素内に記述します。また、テンプレート内に@clickプロパティを記述し、pressed
プロパティの真偽値を切り替えるtoggle()
関数をバインディングします。
@customElement('toggle-button')
export class ToggleButton extends LitElement {
@property({
type: Boolean,
reflect: true,
})
pressed = false;
toggle() {
this.pressed = !this.pressed;
}
render() {
return html`
<button class="c-button" @click="${this.toggle}">
${this.pressed ? 'ON' : 'OFF'}
</button>
`;
}
}
こうすることで、クリックするたびにtoggle()
関数で属性が更新され、pressedプロパティがtrue
の値の場合、HTML内にpressed
属性が付与されます。
ここまでのコードをブラウザで実行すると以下のキャプチャのようになります。
スタイルを設定
最後にボタンのスタイルを付与しましょう。スタイルに必要なLitElementライブラリを読み込み、さきほど属性として付与した際に押したボタンのスタイルを設定します。
import { customElement, property, LitElement, html, css } from 'lit-element';
@customElement('toggle-button')
export class ToggleButton extends LitElement {
@property({
type: Boolean,
reflect: true,
})
pressed = false;
static get styles() {
return css`
:host {
--base-color: #c7f8f9;
--hover-color: #6ab1c9;
}
.c-button {
background-color: transparent;
color: var(--base-color);
font-size: 1.5em;
letter-spacing: 0.1em;
border: 3px solid var(--base-color);
margin-bottom: 30px;
padding: 1rem 3rem;
width: 200px;
display: inline-block;
cursor: pointer;
border-radius: 5px;
}
:host([pressed]) .c-button {
background-color: var(--base-color);
color: var(--hover-color);
}`;
}
// (省略)...
}
ここまでのコードをブラウザで実行すると以下のキャプチャのようになります。以上で、かんたんなコンポーネントの完成です。
ビルド
最後にビルドをしましょう。ビルドコマンドは以下です。
npm run build
ビルド時、Snowpackはアプリケーションの依存ライブラリをESM importsで読み込めるよう変換します。コンポーネントはbuild/_dist_/
フォルダに、依存パッケージはbuild/web_modules/
にそれぞれ出力されます。
Snowpackはモジュールバンドラーをデフォルトでは備えておらず、公式プラグインとして提供されている@snowpack/plugin-webpackや@snowpack/plugin-parcelを導入することで、ESM importsに対応していないレガシーブラウザに対応することが可能です。ただし、バンドラーを導入していても、develop
コマンドではES Modulesで出力されるため注意が必要です。