式
Litテンプレートには、式と呼ばれる動的な値を含めることができます。式は任意のJavaScript式です。式はテンプレートが評価されるときに評価され、式の結果はテンプレートのレンダリング時に含まれます。Litコンポーネントでは、これは`render`メソッドが呼び出されるたびに発生します。
式はテンプレート内の特定の場所にのみ配置でき、式の解釈方法は式の出現場所によって異なります。要素タグ自体の中にある式は要素に影響します。子ノードが配置される要素のコンテンツ内にある式は、子ノードまたはテキストをレンダリングします。
式の有効な値は、式の出現場所によって異なります。一般的に、すべての式は文字列や数値などのプリミティブ値を受け入れ、一部の式は追加の値型をサポートします。さらに、すべての式は*ディレクティブ*を受け入れることができます。ディレクティブとは、式の処理方法とレンダリング方法をカスタマイズする特別な関数です。詳細はカスタムディレクティブを参照してください。
以下は、各式のタイプの詳細情報に続く簡単なリファレンスです。
タイプ | 例 |
---|---|
| |
| |
| |
| |
| |
|
この基本的な例では、さまざまな種類の式を示しています。
以下のセクションでは、各種類の式について詳しく説明します。テンプレートの構造の詳細については、整形式のHTMLと有効な式の場所を参照してください。
要素の開始タグと終了タグの間に配置される式は、要素に子ノードを追加できます。例えば
html`<p>Hello, ${name}</p>`
または
html`<main>${bodyText}</main>`
子位置の式は、さまざまな種類の値を取ることができます。
- 文字列、数値、ブール値などのプリミティブ値。
- `html`関数(または式が`<svg>`要素内にある場合は`svg`関数)で作成された`TemplateResult`オブジェクト。
- DOMノード。
- センチネル値`nothing`と`noChange`。
- サポートされている型の配列または反復可能オブジェクト。
プリミティブ値
「プリミティブ値」へのパーマリンクLitは、ほとんどすべてのプリミティブ値をレンダリングでき、テキストコンテンツに補間されるときに文字列に変換します。
`5`のような数値は文字列`'5'`としてレンダリングされます。ビッグイントも同様に扱われます。
ブール値`true`は`'true'`としてレンダリングされ、`false`は`'false'`としてレンダリングされますが、このようにブール値をレンダリングすることはまれです。代わりに、ブール値は通常、条件分岐で使用され、他の適切な値をレンダリングします。条件分岐の詳細については、条件分岐を参照してください。
空の文字列`''`、`null`、および`undefined`は特別に扱われ、何もレンダリングされません。詳細は子コンテンツの削除を参照してください。
シンボル値は文字列に変換できず、子式に配置するとエラーをスローします。
センチネル値
「センチネル値」へのパーマリンクLitは、子式で使用できる特別なセンチネル値をいくつか提供しています。
`noChange`センチネル値は、式の既存の値を変更しません。これは通常、カスタムディレクティブで使用されます。詳細は変更なしのシグナリングを参照してください。
`nothing`センチネルは何もレンダリングしません。詳細は子コンテンツの削除を参照してください。
テンプレート
「テンプレート」へのパーマリンク子位置の式は`TemplateResult`を返すことができるため、テンプレートを入れ子にして組み合わせることができます。
const nav = html`<nav>...</nav>`;
const page = html`
${nav}
<main>...</main>
`;
これは、プレーンJavaScriptを使用して条件付きテンプレート、繰り返しテンプレートなどを作成できることを意味します。
html`
${this.user.isloggedIn
? html`Welcome ${this.user.name}`
: html`Please log in`
}
`;
条件分岐の詳細については、条件分岐を参照してください。
JavaScriptを使用して繰り返しテンプレートを作成する方法の詳細については、リストを参照してください。
DOMノード
「DOMノード」へのパーマリンク任意のDOMノードを子式に渡すことができます。通常、DOMノードは`html`を使用してテンプレートを指定することでレンダリングする必要がありますが、必要に応じてDOMノードをこのように直接レンダリングできます。ノードはその時点でDOMツリーにアタッチされ、現在の親から削除されます。
const div = document.createElement('div');
const page = html`
${div}
<p>This is some text</p>
`;
サポートされている型の配列または反復可能オブジェクト
「サポートされている型の配列または反復可能オブジェクト」へのパーマリンク式は、サポートされている型の任意の組み合わせの配列または反復可能オブジェクトを返すこともできます。この機能をArrayの`map`メソッドなどの標準JavaScriptと組み合わせて使用すると、繰り返しテンプレートとリストを作成できます。例については、リストを参照してください。
子コンテンツの削除
「子コンテンツの削除」へのパーマリンク値`null`、`undefined`、空の文字列`''`、およびLitの`nothing`センチネル値は、以前にレンダリングされたコンテンツを削除し、ノードをレンダリングしません。
子コンテンツの設定または削除は、多くの場合、条件に基づいて行われます。詳細は条件付きで何もレンダリングしないを参照してください。
ノードをレンダリングしないことは、式がフォールバックコンテンツを持つ`slot`を含むシャドウDOMを持つ要素の子である場合に重要です。ノードをレンダリングしないと、フォールバックコンテンツがレンダリングされます。詳細はフォールバックコンテンツを参照してください。
式を使用して子ノードを追加することに加えて、式を使用して要素の属性とプロパティを設定することもできます。
デフォルトでは、属性の値の式は属性を設定します。
html`<div class=${this.textClass}>Stylish text.</div>`;
属性値は常に文字列であるため、式は文字列に変換できる値を返す必要があります。
式が属性値全体を構成する場合は、引用符を省略できます。式が属性値の一部のみを構成する場合は、値全体を引用符で囲む必要があります。
html`<img src="/images/${this.image}">`;
注:一部のプリミティブ値は属性で特別に処理されます。ブール値は文字列に変換されるため、たとえば、`false`は`'false'`としてレンダリングされます。 `undefined`と`null`はどちらも属性に空の文字列としてレンダリングされます。
ブール属性
「ブール属性」へのパーマリンクブール属性を設定するには、属性名に`?`プレフィックスを使用します。式がtruthy値に評価された場合は属性が追加され、falsy値に評価された場合は削除されます。
html`<div ?hidden=${!this.showAdditional}>This text may be hidden.</div>`;
属性の削除
「属性の削除」へのパーマリンク特定の条件下でのみ属性を設定し、それ以外の場合は属性を削除する場合があります。 `disabled`や`hidden`などの一般的な「ブール属性」の場合、truthy値の場合は属性を空の文字列に設定し、それ以外の場合は削除するには、ブール属性を使用します。ただし、属性を追加または削除するための別の条件が必要になる場合があります。
例えば、以下を考えてみます。
html`<img src="/images/${this.imagePath}/${this.imageFile}">`;
`this.imagePath`または`this.imageFile`が定義されていない場合、`src`属性は設定しないでください。設定すると、無効なネットワークリクエストが発生します。
Litの`nothing`センチネル値は、属性値の式が`nothing`に評価されたときに属性を削除することで、この問題に対処します。
html`<img src="/images/${this.imagePath ?? nothing}/${this.imageFile ?? nothing}">`;
この例では、`src` 属性を設定するには、`this.imagePath` と `this.imageFile` プロパティの**両方**を定義する必要があります。`??` null 合体演算子 は、左辺値が `null` または `undefined` の場合、右辺値を返します。
Lit は、`value ?? nothing` の糖衣構文である ifDefined ディレクティブも提供しています。
html`<img src="/images/${ifDefined(this.imagePath)}/${ifDefined(this.imageFile)}">`;
値が truthy でない場合に属性を削除して、`false` または空文字列 `''` の値で属性が削除されるようにすることもできます。たとえば、`this.ariaLabel` のデフォルト値が空文字列 `''` である要素を考えてみましょう。
html`<button aria-label="${this.ariaLabel || nothing}"></button>`
この例では、`aria-label` 属性は `this.ariaLabel` が空文字列でない場合にのみレンダリングされます。
属性の設定または削除は、多くの場合、条件に基づいて行われます。詳細については、条件付きで何もレンダリングしない を参照してください。
プロパティ式
「プロパティ式」へのパーマリンク`.` プレフィックスとプロパティ名を使用して、要素に JavaScript プロパティを設定できます。
html`<input .value=${this.itemCount}>`;
上記のコードの動作は、`input` 要素の `value` プロパティを直接設定するのと同じです。例:
inputEl.value = this.itemCount;
プロパティ式構文を使用して、複雑なデータをツリーの下位のサブコンポーネントに渡すことができます。たとえば、`listItems` プロパティを持つ `my-list` コンポーネントがある場合、オブジェクトの配列を渡すことができます。
html`<my-list .listItems=${this.items}></my-list>`;
この例のプロパティ名 `listItems` は大文字と小文字が混在していることに注意してください。HTML *属性* は大文字と小文字が区別されませんが、Lit はテンプレートを処理するときにプロパティ名の大文字と小文字を保持します。
コンポーネントプロパティの詳細については、リアクティブプロパティ を参照してください。
イベントリスナー式
「イベントリスナー式」へのパーマリンクテンプレートには、宣言型のイベントリスナーを含めることもできます。プレフィックス `@` の後にイベント名を続けます。式はイベントリスナーに評価される必要があります。
html`<button @click=${this.clickHandler}>Click Me!</button>`;
これは、ボタン要素で `addEventListener('click', this.clickHandler)` を呼び出すのと似ています。
イベントリスナーは、プレーン関数、または `handleEvent` メソッドを持つオブジェクトのいずれかになります。これは、標準の `addEventListener` メソッドの `listener` 引数と同じです。
Lit コンポーネントでは、イベントリスナーはコンポーネントに自動的にバインドされるため、ハンドラー内で `this` 値を使用してコンポーネントインスタンスを参照できます。
clickHandler() {
this.clickCount++;
}
コンポーネントイベントの詳細については、イベント を参照してください。
要素ディレクティブ
「要素式」へのパーマリンク要素の単一のプロパティまたは属性ではなく、要素インスタンスにアクセスする式を追加することもできます。
html`<div ${myDirective()}></div>`
要素式は、ディレクティブ でのみ機能します。要素式内の他の値型は無視されます。
要素式で使用できる組み込みディレクティブの1つは、`ref` ディレクティブです。レンダリングされた要素への参照を提供します。
html`<button ${ref(this.myRef)}></button>`;
詳細については、ref を参照してください。
整形式のHTML
「整形式の HTML」へのパーマリンクLit テンプレートは整形式の HTML である必要があります。テンプレートは、値が補間される前に、ブラウザの組み込み HTML パーサーによって解析されます。整形式のテンプレートを作成するには、次のルールに従ってください。
すべての式が空の値に置き換えられた場合、テンプレートは整形式の HTML である必要があります。
テンプレートには、複数のトップレベル要素とテキストを含めることができます。
テンプレートには、閉じられていない要素を含めないでください。HTML パーサーによって閉じられます。
// HTML parser closes this div after "Some text"
const template1 = html`<div class="broken-div">Some text`;
// When joined, "more text" does not end up in .broken-div
const template2 = html`${template1} more text. </div>`;
ブラウザの組み込みパーサーは非常に寛容であるため、不正な形式のテンプレートのほとんどのケースは実行時に検出できません。そのため、警告は表示されず、期待どおりに動作しないテンプレートが表示されます。開発中にテンプレートの問題を見つけるために、リンティングツール と IDE プラグイン を使用することをお勧めします。
有効な式の場所
「有効な式の場所」へのパーマリンク式は、HTML で属性値と子要素を配置できる場所に**のみ**配置できます。
<!-- attribute values -->
<div label=${label}></div>
<button ?disabled=${isDisabled}>Click me!</button>
<input .value=${currentValue}>
<button @click=${this.handleClick()}>
<!-- child content -->
<div>${textContent}</div>
要素式は、開始タグ内のタグ名の後に配置できます。
<div ${ref(elementReference)}></div>
無効な場所
「無効な場所」へのパーマリンク式は、一般的に次の場所には表示しないでください。
タグ名または属性名が表示される場所。Lit はこの位置の値の動的な変更をサポートしておらず、開発モードでエラーが発生します。
<!-- ERROR -->
<${tagName}></${tagName}>
<!-- ERROR -->
<div ${attrName}=true></div>
`<template>` 要素のコンテンツ内(テンプレート要素自体の属性式は許可されています)。Lit はテンプレートコンテンツを再帰的に処理して式を動的に更新せず、開発モードでエラーが発生します。
<!-- ERROR -->
<template>${content}</template>
<!-- OK -->
<template id="${attrValue}">static content ok</template>
`<textarea>` 要素のコンテンツ内(textarea 要素自体の属性式は許可されています)。Lit は textarea にコンテンツをレンダリングできますが、textarea を編集すると、Lit が動的更新に使用する DOM への参照が壊れ、Lit は開発モードで警告を発します。代わりに、textarea の `.value` プロパティにバインドしてください。
<!-- BEWARE -->
<textarea>${content}</textarea>
<!-- OK -->
<textarea .value=${content}></textarea>
<!-- OK -->
<textarea id="${attrValue}">static content ok</textarea>
同様に、`contenteditable` 属性を持つ要素内。代わりに、要素の `.innerText` プロパティにバインドしてください。
<!-- BEWARE -->
<div contenteditable>${content}</div>
<!-- OK -->
<div contenteditable .innerText=${content}></div>
<!-- OK -->
<div contenteditable id="${attrValue}">static content ok</div>
HTML コメント内。Lit はコメント内の式を更新せず、式は Lit トークン文字列でレンダリングされます。ただし、これは後続の式を壊すことはないため、式を含む可能性のある HTML ブロックを開発中にコメントアウトしても安全です。
<!-- will not update: ${value} -->
ShadyCSS ポリフィルを使用する場合の `<style>` 要素内。詳細については、式とスタイル要素 を参照してください。
上記のすべての無効なケースの式は、静的式 を使用する場合に有効ですが、非効率性があるため、パフォーマンスに敏感な更新には使用しないでください(下記参照)。
静的式は、Lit によってテンプレートが HTML として処理される**前**に、テンプレートに補間される特別な値を返します。それらはテンプレートの静的 HTML の一部になるため、テンプレートのどこにでも配置できます。属性名やタグ名など、通常は式が許可されない場所にも配置できます。
静的式を使用するには、Lit の `static-html` モジュールから `html` または `svg` テンプレートタグの特別なバージョンをインポートする必要があります。
import {html, literal} from 'lit/static-html.js';
`static-html` モジュールには、静的式をサポートする `html` および `svg` タグ関数が含まれており、`lit` モジュールで提供されている標準バージョンではなく、これらを使用する必要があります。`literal` タグ関数を使用して、静的式を作成します。
静的式は、変更される可能性が低い構成オプションや、通常の式ではできないテンプレートの部分のカスタマイズに使用できます。有効な式の場所 のセクションで詳細を確認してください。たとえば、`my-button` コンポーネントは `<button>` タグをレンダリングしますが、サブクラスは代わりに `<a>` タグをレンダリングする場合があります。これは、設定が頻繁に変更されず、HTML タグのカスタマイズが通常の式ではできないため、静的式を使用するのに適した場所です。
import {LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import {html, literal} from 'lit/static-html.js';
@customElement('my-button')
class MyButton extends LitElement {
tag = literal`button`;
activeAttribute = literal`active`;
@property() caption = 'Hello static';
@property({type: Boolean}) active = false;
render() {
return html`
<${this.tag} ${this.activeAttribute}=${this.active}>
<p>${this.caption}</p>
</${this.tag}>`;
}
}
import {LitElement} from 'lit';
import {html, literal} from 'lit/static-html.js';
class MyButton extends LitElement {
static properties = {
caption: {},
active: {type: Boolean},
};
tag = literal`button`;
activeAttribute = literal`active`;
constructor() {
super();
this.caption = 'Hello static';
this.active = false;
}
render() {
return html`
<${this.tag} ${this.activeAttribute}=${this.active}>
<p>${this.caption}</p>
</${this.tag}>`;
}
}
customElements.define('my-button', MyButton);
@customElement('my-anchor')
class MyAnchor extends MyButton {
tag = literal`a`;
}
class MyAnchor extends MyButton {
tag = literal`a`;
}
customElements.define('my-anchor', MyAnchor);
**静的式の値を変更するとコストがかかります。** `literal` 値を使用する式は、新しいテンプレートが再解析され、各バリエーションがメモリに保持されるため、頻繁に変更しないでください。
上記の例では、テンプレートが再レンダリングされ、`this.caption` または `this.active` が変更された場合、Lit はテンプレートを効率的に更新し、影響を受ける式のみを変更します。ただし、`this.tag` または `this.activeAttribute` が変更された場合、それらは `literal` でタグ付けされた静的値であるため、まったく新しいテンプレートが作成されます。DOM が完全に再レンダリングされるため、更新は非効率的です。さらに、式に渡される `literal` 値を変更すると、再レンダリングのパフォーマンスを向上させるために各一意のテンプレートがメモリにキャッシュされるため、メモリ使用量が増加します。
これらの理由から、`literal` を使用する式の変更を最小限に抑え、リアクティブプロパティは変更を意図しているため、リアクティブプロパティを使用して `literal` 値を変更することは避けてください。
テンプレート構造
「テンプレート構造」へのパーマリンク静的値が補間された後、テンプレートは通常の Lit テンプレートのように整形式である必要があります。そうでない場合、テンプレートの動的式が正しく機能しない可能性があります。詳細については、整形式の HTML セクションを参照してください。
非リテラル静的
「非リテラル静的」へのパーマリンクまれに、スクリプトで定義されていない静的 HTML をテンプレートに補間する必要がある場合があります。そのため、`literal` 関数でタグ付けすることはできません。このような場合は、`unsafeStatic()` 関数を使用して、スクリプト以外のソースからの文字列に基づいて静的 HTML を作成できます。
import {html, unsafeStatic} from 'lit/static-html.js';
**信頼できるコンテンツ専用。** `unsafeStatic()` で *unsafe* を使用していることに注意してください。`unsafeStatic()` に渡される文字列は開発者によって制御される必要があり、信頼できないコンテンツを含めてはなりません。これは、サニタイズなしで HTML として直接解析されるためです。信頼できないコンテンツの例としては、クエリ文字列パラメータやユーザー入力からの値が挙げられます。このディレクティブでレンダリングされた信頼できないコンテンツは、クロスサイトスクリプティング(XSS) の脆弱性につながる可能性があります。
@customElement('my-button')
class MyButton extends LitElement {
@property() caption = 'Hello static';
@property({type: Boolean}) active = false;
render() {
// These strings MUST be trusted, otherwise this is an XSS vulnerability
const tag = getTagName();
const activeAttribute = getActiveAttribute();
return html`
<${unsafeStatic(tag)} ${unsafeStatic(activeAttribute)}=${this.active}>
<p>${this.caption}</p>
</${unsafeStatic(tag)}>`;
}
}
class MyButton extends LitElement {
static properties = {
caption: {},
active: {type: Boolean},
};
constructor() {
super();
this.caption = 'Hello static';
this.active = false;
}
render() {
// These strings MUST be trusted, otherwise this is an XSS vulnerability
const tag = getTagName();
const activeAttribute = getActiveAttribute();
return html`
<${unsafeStatic(tag)} ${unsafeStatic(activeAttribute)}=${this.active}>
<p>${this.caption}</p>
</${unsafeStatic(tag)}>`;
}
}
customElements.define('my-button', MyButton);
`unsafeStatic` を使用する場合の動作は `literal` と同じ注意事項があることに注意してください。値を変更すると新しいテンプレートが解析され、メモリにキャッシュされるため、頻繁に変更しないでください。