組み込みディレクティブ
ディレクティブは、式のレンダリング方法をカスタマイズすることでLitを拡張できる関数です。Litには、さまざまなレンダリングニーズに対応するための組み込みディレクティブが多数含まれています。
ディレクティブ | 概要 |
---|---|
スタイリング | |
オブジェクトに基づいて、要素にクラスのリストを割り当てます。 | |
オブジェクトに基づいて、要素にスタイルプロパティのリストを設定します。 | |
ループと条件 | |
条件に基づいて、2つのテンプレートのいずれかをレンダリングします。 | |
キー値に基づいて、多数のテンプレートのいずれかをレンダリングします。 | |
関数を使用して、イテラブルを変換します。 | |
データ差分とDOMの安定性を実現するために、オプションのキー設定を使用して、イテラブルからDOMに値をレンダリングします。 | |
イテラブルからの値を、結合子値と交互に配置します。 | |
シーケンス内の数値のイテラブルを作成します。これは、特定の回数繰り返す場合に役立ちます。 | |
値が定義されている場合は属性を設定し、未定義の場合は属性を削除します。 | |
キャッシュと変更検出 | |
DOMを破棄するのではなく、テンプレートを変更するときにレンダリングされたDOMをキャッシュします。 | |
レンダリング可能な値を一意のキーに関連付け、キーが変更された場合はDOMを強制的に再レンダリングします。 | |
依存関係のいずれかが変更された場合にのみ、テンプレートを再評価します。 | |
属性またはプロパティが最後にレンダリングされた値ではなく、ライブDOMの値と異なる場合に設定します。 | |
レンダリングされたDOMの参照 | |
テンプレートでレンダリングされた要素への参照を取得します。 | |
特殊な値のレンダリング | |
| |
文字列をテキストではなくHTMLとしてレンダリングします。 | |
文字列をテキストではなくSVGとしてレンダリングします。 | |
非同期レンダリング | |
1つ以上のPromiseが解決するまで、プレースホルダーコンテンツをレンダリングします。 | |
| |
|
使用するものだけをバンドルしてください。 これらはLitパッケージの一部であるため、「組み込み」ディレクティブと呼ばれています。ただし、各ディレクティブは個別のモジュールであるため、アプリはインポートしたディレクティブのみをバンドルします。
独自のディレクティブを作成することもできます。詳細については、カスタムディレクティブを参照してください。
スタイリング
「スタイリング」へのパーマリンクclassMap
「classMap」へのパーマリンクオブジェクトに基づいて、要素にクラスのリストを設定します。
インポート |
|
シグネチャ |
|
使用可能な場所 |
|
classMap
ディレクティブは、element.classList
APIを使用して、ユーザーから渡されたオブジェクトに基づいて、要素にクラスを効率的に追加および削除します。オブジェクト内の各キーはクラス名として扱われ、キーに関連付けられた値が真の場合、そのクラスが要素に追加されます。後続のレンダリングでは、偽またはオブジェクトに存在しなくなった以前に設定されたクラスは削除されます。
@customElement('my-element')
class MyElement extends LitElement {
@property({type: Boolean})
enabled = false;
render() {
const classes = { enabled: this.enabled, hidden: false };
return html`<div class=${classMap(classes)}>Classy text</div>`;
}
}
class MyElement extends LitElement {
static properties = {
enabled: {type: Boolean},
};
constructor() {
super();
this.enabled = false;
}
render() {
const classes = { enabled: this.enabled, hidden: false };
return html`<div class=${classMap(classes)}>Classy text</div>`;
}
}
customElements.define('my-element', MyElement);
classMap
はclass
属性内の唯一の式である必要がありますが、静的な値と組み合わせることができます
html`<div class="my-widget ${classMap(dynamicClasses)}">Static and dynamic</div>`;
playgroundでclassMap
を詳しく調べてください。
styleMap
「styleMap」へのパーマリンクオブジェクトに基づいて、要素にスタイルプロパティのリストを設定します。
インポート |
|
シグネチャ |
|
使用可能な場所 |
|
styleMap
ディレクティブは、element.style
APIを使用して、ユーザーから渡されたオブジェクトに基づいて、要素にインラインスタイルを効率的に追加および削除します。オブジェクト内の各キーはスタイルプロパティ名として扱われ、値はそのプロパティの値として扱われます。後続のレンダリングでは、未定義またはnull
の以前に設定されたスタイルプロパティはすべて削除されます(null
に設定されます)。
@customElement('my-element')
class MyElement extends LitElement {
@property({type: Boolean})
enabled = false;
render() {
const styles = { backgroundColor: this.enabled ? 'blue' : 'gray', color: 'white' };
return html`<p style=${styleMap(styles)}>Hello style!</p>`;
}
}
class MyElement extends LitElement {
static properties = {
enabled: {type: Boolean},
};
constructor() {
super();
this.enabled = false;
}
render() {
const styles = { backgroundColor: this.enabled ? 'blue' : 'gray', color: 'white' };
return html`<p style=${styleMap(styles)}>Hello style!</p>`;
}
}
customElements.define('my-element', MyElement);
ダッシュを含むCSSプロパティの場合、キャメルケースの同等のものを使用するか、プロパティ名を引用符で囲むことができます。たとえば、CSSプロパティfont-family
をfontFamily
または'font-family'
のいずれかとして記述できます。
{ fontFamily: 'roboto' }
{ 'font-family': 'roboto' }
--custom-color
などのCSSカスタムプロパティを参照するには、プロパティ名全体を引用符で囲みます。
{ '--custom-color': 'steelblue' }
styleMap
はstyle
属性内の唯一の式である必要がありますが、静的な値と組み合わせることができます
html`<p style="color: white; ${styleMap(moreStyles)}">More styles!</p>`;
playgroundでstyleMap
を詳しく調べてください。
ループと条件
「ループと条件」へのパーマリンクwhen
「when」へのパーマリンク条件に基づいて、2つのテンプレートのいずれかをレンダリングします。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意 |
condition
がtrueの場合はtrueCase()
の呼び出しの結果を返し、それ以外の場合はfalseCase
が定義されている場合はfalseCase()
の呼び出しの結果を返します。
これは、elseなしでインライン条件を少しだけ記述しやすくする三項式の便利なラッパーです。
class MyElement extends LitElement {
render() {
return html`
${when(this.user, () => html`User: ${this.user.username}`, () => html`Sign In...`)}
`;
}
}
choose
「choose」へのパーマリンク指定されたvalue
をケースに一致させることに基づいて、ケースのリストからテンプレート関数を選択して評価します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意 |
ケースは[caseValue, func]
として構造化されています。value
は厳密な等価性によってcaseValue
に一致します。最初のマッチが選択されます。ケースの値には、プリミティブ、オブジェクト、シンボルなど、任意の型を指定できます。
これはswitch文に似ていますが、式としてであり、フォールスルーはありません。
class MyElement extends LitElement {
render() {
return html`
${choose(this.section, [
['home', () => html`<h1>Home</h1>`],
['about', () => html`<h1>About</h1>`]
],
() => html`<h1>Error</h1>`)}
`;
}
}
items
の各値でf(value)
を呼び出した結果を含むイテラブルを返します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意 |
map()
は、for/ofループの単純なラッパーであり、式でイテラブルを少し簡単に操作できるようにします。map()
は常にその場で作成されたDOMを更新します。差分やDOMの移動は行いません。それが必要な場合は、repeatを参照してください。map()
はrepeat()
よりも小さく、高速であるため、差分やDOMの安定性が必要ない場合は、map()
を優先してください。
class MyElement extends LitElement {
render() {
return html`
<ul>
${map(items, (i) => html`<li>${i}</li>`)}
</ul>
`;
}
}
repeat
「repeat」へのパーマリンクデータ差分とDOMの安定性を実現するために、オプションのキー設定を使用して、イテラブルからDOMに値をレンダリングします。
インポート |
|
シグネチャ |
|
使用可能な場所 | 子式 |
イテラブルから生成された一連の値(通常はTemplateResults
)を繰り返し、イテラブルが変更されたときにこれらのアイテムを効率的に更新します。keyFn
が指定されている場合、キーからDOMへの関連付けは、必要に応じて生成されたDOMを移動することで更新間で維持され、挿入と削除のために最小限の不要な作業を実行するため、一般的にrepeat
を使用する最も効率的な方法です。
キー関数を使用していない場合は、map()
の使用を検討する必要があります。
@customElement('my-element')
class MyElement extends LitElement {
@property()
items: Array<{id: number, name: string}> = [];
render() {
return html`
<ul>
${repeat(this.items, (item) => item.id, (item, index) => html`
<li>${index}: ${item.name}</li>`)}
</ul>
`;
}
}
class MyElement extends LitElement {
static properties = {
items: {},
};
constructor() {
super();
this.items = [];
}
render() {
return html`
<ul>
${repeat(this.items, (item) => item.id, (item, index) => html`
<li>${index}: ${item.name}</li>`)}
</ul>
`;
}
}
customElements.define('my-element', MyElement);
keyFn
が提供されていない場合、repeat
はアイテムから値への単純なマップと同様に動作し、DOMは潜在的に異なるアイテムに対して再利用されます。
repeat
を使用する場合と標準のJavaScriptフロー制御を使用する場合の議論については、mapまたはrepeatを使用する場合を参照してください。
playgroundでrepeat
を詳しく調べてください。
join
「join」へのパーマリンクitems
の値がjoiner
の値と交互に配置されたイテラブルを返します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意 |
class MyElement extends LitElement {
render() {
return html`
${join(
map(menuItems, (i) => html`<a href=${i.href}>${i.label}</a>`),
html`<span class="separator">|</span>`
)}
`;
}
}
range
「range」へのパーマリンクstart
からend
(排他的)までの整数で、step
ずつ増分するイテラブルを返します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意 |
class MyElement extends LitElement {
render() {
return html`
${map(range(8), (i) => html`${i + 1}`)}
`;
}
}
ifDefined
「ifDefined」へのパーマリンク値が定義されている場合は属性を設定し、未定義の場合は属性を削除します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 属性式 |
AttributePartsの場合、値が定義されている場合は属性を設定し、値が未定義(undefined
またはnull
)の場合は属性を削除します。他の部分型の場合、このディレクティブはノーオペレーションです。
単一の属性値に複数の式が存在する場合、いずれかの式でifDefined
を使用し、undefined
/null
と評価された場合、属性は削除されます。これは、URLの必要な部分が定義されていない場合に属性を設定すべきではない場合、404を防ぐためにURL属性を設定する場合に特に役立ちます。
@customElement('my-element')
class MyElement extends LitElement {
@property()
filename: string | undefined = undefined;
@property()
size: string | undefined = undefined;
render() {
// src attribute not rendered if either size or filename are undefined
return html`<img src="/images/${ifDefined(this.size)}/${ifDefined(this.filename)}">`;
}
}
class MyElement extends LitElement {
static properties = {
filename: {},
size: {},
};
constructor() {
super();
this.filename = undefined;
this.size = undefined;
}
render() {
// src attribute not rendered if either size or filename are undefined
return html`<img src="/images/${ifDefined(this.size)}/${ifDefined(this.filename)}">`;
}
}
customElements.define('my-element', MyEleent);
playgroundでifDefined
を詳しく調べてください。
キャッシュと変更検出
「キャッシュと変更検出」へのパーマリンクcache
「cache」へのパーマリンクDOMを破棄するのではなく、テンプレートを変更するときにレンダリングされたDOMをキャッシュします。このディレクティブを使用すると、大きなテンプレート間を頻繁に切り替える場合にレンダリングパフォーマンスを最適化できます。
インポート |
|
シグネチャ |
|
使用可能な場所 | 子式 |
cache
に渡された値が1つ以上のTemplateResult
の間で変化する場合、特定のテンプレートのレンダリングされたDOMノードは、使用されていないときにキャッシュされます。テンプレートが変更されると、ディレクティブは新しい値に切り替える前に現在のDOMノードをキャッシュし、DOMノードを新しく作成するのではなく、以前にレンダリングされた値に切り替えるときにキャッシュから復元します。
const detailView = (data) => html`<div>...</div>`;
const summaryView = (data) => html`<div>...</div>`;
@customElement('my-element')
class MyElement extends LitElement {
@property()
data = {showDetails: true, /*...*/ };
render() {
return html`${cache(this.data.showDetails
? detailView(this.data)
: summaryView(this.data)
)}`;
}
}
const detailView = (data) => html`<div>...</div>`;
const summaryView = (data) => html`<div>...</div>`;
class MyElement extends LitElement {
static properties = {
data: {},
};
constructor() {
super();
this.data = {showDetails: true, /*...*/ };
}
render() {
return html`${cache(this.data.showDetails
? detailView(this.data)
: summaryView(this.data)
)}`;
}
}
customElements.define('my-element', MyElement);
Litがテンプレートを再レンダリングする場合、変更された部分のみを更新します。必要な以上のDOMを作成または削除することはありません。ただし、あるテンプレートから別のテンプレートに切り替える場合、Litは古いDOMを削除し、新しいDOMツリーをレンダリングします。
cache
ディレクティブは、指定された式と入力テンプレートに対して生成された DOM をキャッシュします。上記の例では、summaryView
と detailView
の両方のテンプレートの DOM をキャッシュしています。あるビューから別のビューに切り替えるとき、Lit は新しいビューのキャッシュされたバージョンを挿入し、最新のデータで更新します。これにより、これらのビューが頻繁に切り替えられる場合にレンダリングパフォーマンスを向上させることができます。
cache
については、プレイグラウンドで詳しく調べてください。
keyed
「キー付き」へのパーマリンクレンダリング可能な値を一意のキーに関連付けます。キーが変更されると、値 (テンプレートなど) が同じであっても、前の DOM は削除および破棄されてから次の値がレンダリングされます。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意の式 |
keyed
は、状態を持つ要素をレンダリングしていて、重要なデータが変更されたときに要素のすべての状態をクリアする必要がある場合に役立ちます。これは基本的に、Lit のデフォルトの DOM 再利用戦略をオプトアウトします。
keyed
は、"enter" または "exit" アニメーションのために新しい要素を強制的に作成する必要がある場合、一部のアニメーションシナリオでも役立ちます。
@customElement('my-element')
class MyElement extends LitElement {
@property()
userId: string = '';
render() {
return html`
<div>
${keyed(this.userId, html`<user-card .userId=${this.userId}></user-card>`)}
</div>`;
}
}
class MyElement extends LitElement {
static properties = {
userId: {},
};
constructor() {
super();
this.userId = '';
}
render() {
return html`
<div>
${keyed(this.userId, html`<user-card .userId=${this.userId}></user-card>`)}
</div>`;
}
}
customElements.define('my-element', MyElement);
guard
「ガード」へのパーマリンク不要な作業を防ぎ、レンダリングパフォーマンスを最適化するために、依存関係のいずれかが変更された場合にのみテンプレートを再評価します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意の式 |
valueFn
によって返される値をレンダリングし、依存関係のいずれかの識別子が変更された場合にのみ valueFn
を再評価します。
ここで
dependencies
は、変更を監視する値の配列です。valueFn
は、レンダリング可能な値を返す関数です。
guard
は、データが更新されるまでコストのかかる処理を防ぐことで、イミュータブルなデータパターンで役立ちます。
@customElement('my-element')
class MyElement extends LitElement {
@property()
value: string = '';
render() {
return html`
<div>
${guard([this.value], () => calculateSHA(this.value))}
</div>`;
}
}
class MyElement extends LitElement {
static properties = {
value: {},
};
constructor() {
super();
this.value = '';
}
render() {
return html`
<div>
${guard([this.value], () => calculateSHA(this.value))}
</div>`;
}
}
customElements.define('my-element', MyElement);
この場合、コストのかかる calculateSHA
関数は、value
プロパティが変更された場合にのみ実行されます。
guard
については、プレイグラウンドで詳しく調べてください。
live
「ライブ」へのパーマリンク属性またはプロパティが最後にレンダリングされた値ではなく、ライブDOMの値と異なる場合に設定します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 属性またはプロパティ式 |
値を更新するかどうかを判断するときに、Lit のデフォルトの動作である最後に設定された値に対するチェックではなく、ライブ DOM 値に対して式値をチェックします。
これは、DOM 値が Lit の外部から変更される可能性がある場合に役立ちます。たとえば、<input>
要素の value
プロパティ、コンテンツ編集可能な要素のテキストを設定する式を使用する場合や、独自のプロパティまたは属性を変更するカスタム要素を使用する場合などです。
このような場合、DOM 値が変更されても、Lit 式を通じて設定された値が変更されていない場合、Lit は DOM 値を更新する必要があることを認識せず、そのままにします。これが望ましくない場合 (DOM 値をバインドされた値で上書きしたい場合) は、live()
ディレクティブを使用します。
@customElement('my-element')
class MyElement extends LitElement {
@property()
data = {value: 'test'};
render() {
return html`<input .value=${live(this.data.value)}>`;
}
}
class MyElement extends LitElement {
static properties = {
data: {},
};
constructor() {
super();
this.data = {value: 'test'};
}
render() {
return html`<input .value=${live(this.data.value)}>`;
}
}
customElements.define('my-element', MyElement);
live()
は、ライブ DOM 値に対して厳密な等価性チェックを実行し、新しい値がライブ値と等しい場合は何も実行しません。これは、式が型変換を引き起こす場合には live()
を使用すべきではないことを意味します。属性式で live()
を使用する場合は、文字列のみが渡されるようにするか、式がすべてのレンダリングで更新されるようにしてください。
live
については、プレイグラウンドで詳しく調べてください。
特殊な値のレンダリング
「特殊な値のレンダリング」へのパーマリンクtemplateContent
「templateContent」へのパーマリンク<template>
要素の内容をレンダリングします。
インポート |
|
シグネチャ |
|
使用可能な場所 | 子式 |
Lit テンプレートは JavaScript でエンコードされているため、動的にするための JavaScript 式を埋め込むことができます。Lit テンプレートに含める必要がある静的な HTML <template>
がある場合は、templateContent
ディレクティブを使用してテンプレートの内容をクローンし、Lit テンプレートに含めることができます。テンプレート要素参照がレンダリング間で変更されない限り、後続のレンダリングは何も行いません。
テンプレートの内容は開発者が管理する必要があり、信頼できない文字列を使用して作成してはならないことに注意してください。信頼できないコンテンツの例には、クエリ文字列パラメーターやユーザー入力からの値が含まれます。このディレクティブでレンダリングされた信頼できないテンプレートは、クロスサイトスクリプティング (XSS) の脆弱性につながる可能性があります。
const templateEl = document.querySelector('template#myContent') as HTMLTemplateElement;
@customElement('my-element')
class MyElement extends LitElement {
render() {
return html`
Here's some content from a template element:
${templateContent(templateEl)}`;
}
}
const templateEl = document.querySelector('template#myContent');
class MyElement extends LitElement {
render() {
return html`
Here's some content from a template element:
${templateContent(templateEl)}`;
}
}
customElements.define('my-element', MyElement);
templateContent
については、プレイグラウンドで詳しく調べてください。
unsafeHTML
「unsafeHTML」へのパーマリンク文字列をテキストではなくHTMLとしてレンダリングします。
インポート |
|
シグネチャ |
|
使用可能な場所 | 子式 |
Lit のテンプレート構文の重要な機能は、テンプレートリテラルから発生した文字列のみが HTML として解析されることです。テンプレートリテラルは信頼できるスクリプトファイルでのみ作成できるため、これは信頼できない HTML を挿入する XSS 攻撃に対する自然な保護として機能します。ただし、データベースからフェッチされた信頼できる HTML コンテンツなど、スクリプトファイルから発生していない HTML を Lit テンプレートでレンダリングする必要がある場合があります。unsafeHTML
ディレクティブは、このような文字列を HTML として解析し、Lit テンプレートでレンダリングします。
unsafeHTML
に渡される文字列は開発者が管理する必要があり、信頼できないコンテンツを含めてはならないことに注意してください。信頼できないコンテンツの例には、クエリ文字列パラメーターやユーザー入力からの値が含まれます。
このディレクティブでレンダリングされた信頼できないコンテンツは、クロスサイトスクリプティング (XSS)、CSS インジェクション、データ流出などの脆弱性につながる可能性があります。unsafeHTML
は innerHTML
を使用して HTML 文字列を解析するため、セキュリティ上の影響は innerHTML
と同じであり、MDN に記載されているとおりです。
const markup = '<h3>Some HTML to render.</h3>';
@customElement('my-element')
class MyElement extends LitElement {
render() {
return html`
Look out, potentially unsafe HTML ahead:
${unsafeHTML(markup)}
`;
}
}
const markup = '<h3>Some HTML to render.</h3>';
class MyElement extends LitElement {
render() {
return html`
Look out, potentially unsafe HTML ahead:
${unsafeHTML(markup)}
`;
}
}
customElements.define('my-element', MyElement);
unsafeHTML
については、プレイグラウンドで詳しく調べてください。
unsafeSVG
「unsafeSVG」へのパーマリンク文字列をテキストではなくSVGとしてレンダリングします。
インポート |
|
シグネチャ |
|
使用可能な場所 | 子式 |
unsafeHTML
と同様に、データベースからフェッチされた信頼できる SVG コンテンツなど、スクリプトファイルから発生していない SVG コンテンツを Lit テンプレートでレンダリングする必要がある場合があります。unsafeSVG
ディレクティブは、このような文字列を SVG として解析し、Lit テンプレートでレンダリングします。
unsafeSVG
に渡される文字列は開発者が管理する必要があり、信頼できないコンテンツを含めてはならないことに注意してください。信頼できないコンテンツの例には、クエリ文字列パラメーターやユーザー入力からの値が含まれます。このディレクティブでレンダリングされた信頼できないコンテンツは、クロスサイトスクリプティング (XSS) の脆弱性につながる可能性があります。
const svg = '<circle cx="50" cy="50" r="40" fill="red" />';
@customElement('my-element')
class MyElement extends LitElement {
render() {
return html`
Look out, potentially unsafe SVG ahead:
<svg width="40" height="40" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg" version="1.1">
${unsafeSVG(svg)}
</svg> `;
}
}
const svg = '<circle cx="50" cy="50" r="40" fill="red" />';
class MyElement extends LitElement {
render() {
return html`
Look out, potentially unsafe SVG ahead:
<svg width="40" height="40" viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg" version="1.1">
${unsafeSVG(svg)}
</svg> `;
}
}
customElements.define('my-element', MyElement);
unsafeSVG
については、プレイグラウンドで詳しく調べてください。
レンダリングされたDOMの参照
「レンダリングされた DOM の参照」へのパーマリンクDOM にレンダリングされた要素への参照を取得します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 要素式 |
Lit でのほとんどの DOM 操作はテンプレートを使用して宣言的に実現できますが、高度な状況ではテンプレートにレンダリングされた要素への参照を取得し、命令的に操作する必要がある場合があります。これが役立つ可能性のある一般的な例としては、フォームコントロールにフォーカスを設定したり、コンテナー要素に対して命令的な DOM 操作ライブラリを呼び出したりする場合などがあります。
テンプレート内の要素に配置すると、ref
ディレクティブはレンダリングされたときにその要素への参照を取得します。要素参照は、Ref
オブジェクトを渡すか、コールバックを渡すかのいずれかの 2 つの方法で取得できます。
Ref
オブジェクトは要素への参照のコンテナとして機能し、ref
モジュールにある createRef
ヘルパーメソッドを使用して作成できます。レンダリング後、Ref
の value
プロパティは要素に設定され、updated
などのレンダリング後のライフサイクルでアクセスできます。
@customElement('my-element')
class MyElement extends LitElement {
inputRef: Ref<HTMLInputElement> = createRef();
render() {
// Passing ref directive a Ref object that will hold the element in .value
return html`<input ${ref(this.inputRef)}>`;
}
firstUpdated() {
const input = this.inputRef.value!;
input.focus();
}
}
class MyElement extends LitElement {
inputRef = createRef();
render() {
// Passing ref directive a Ref object that will hold the element in .value
return html`<input ${ref(this.inputRef)}>`;
}
firstUpdated() {
const input = this.inputRef.value!;
input.focus();
}
}
customElements.define('my-element', MyElement);
ref コールバックを ref
ディレクティブに渡すこともできます。コールバックは、参照される要素が変更されるたびに呼び出されます。ref コールバックが別の要素の位置にレンダリングされた場合、または後続のレンダリングで削除された場合、最初に undefined
で呼び出され、次いで (存在する場合) レンダーされた新しい要素で再度呼び出されます。LitElement
では、コールバックはホスト要素にバインドされて自動的に呼び出されることに注意してください。
@customElement('my-element')
class MyElement extends LitElement {
render() {
// Passing ref directive a change callback
return html`<input ${ref(this.inputChanged)}>`;
}
inputChanged(input?: HTMLInputElement) {
input?.focus();
}
}
class MyElement extends LitElement {
render() {
// Passing ref directive a change callback
return html`<input ${ref(this.inputChanged)}>`;
}
inputChanged(input) {
input?.focus();
}
}
customElements.define('my-element', MyElement);
ref
については、プレイグラウンドで詳しく調べてください。
非同期レンダリング
「非同期レンダリング」へのパーマリンクuntil
「until」へのパーマリンク1つ以上のPromiseが解決するまで、プレースホルダーコンテンツをレンダリングします。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意の式 |
Promise を含む一連の値を受け取ります。値は優先順位順にレンダリングされ、最初の引数が最も優先度が高く、最後の引数が最も優先度が低くなります。値が Promise の場合、解決されるまで、より優先度の低い値がレンダリングされます。
値の優先順位は、非同期データのプレースホルダーコンテンツを作成するために使用できます。たとえば、保留中のコンテンツを含む Promise を最初の (最も優先度の高い) 引数に、Promise ではないロードインジケーターテンプレートを 2 番目の (優先度の低い) 引数として使用できます。ロードインジケーターはすぐにレンダリングされ、Promise が解決されるとプライマリコンテンツがレンダリングされます。
@customElement('my-element')
class MyElement extends LitElement {
@state()
private content = fetch('./content.txt').then(r => r.text());
render() {
return html`${until(this.content, html`<span>Loading...</span>`)}`;
}
}
class MyElement extends LitElement {
static properties = {
content: {state: true},
};
constructor() {
super();
this.content = fetch('./content.txt').then(r => r.text());
}
render() {
return html`${until(this.content, html`<span>Loading...</span>`)}`;
}
}
customElements.define('my-element', MyElement);
until
については、プレイグラウンドで詳しく調べてください。
asyncAppend
「asyncAppend」へのパーマリンクAsyncIterable
からの値が生成されると、DOMに追加します。
インポート |
|
シグネチャ |
|
使用可能な場所 | 子式 |
asyncAppend
は、非同期イテラブルの値をレンダリングし、前の値の後に新しい値をそれぞれ追加します。非同期ジェネレーターも非同期イテラブルプロトコルを実装しているため、asyncAppend
で使用できることに注意してください。
async function *tossCoins(count: number) {
for (let i=0; i<count; i++) {
yield Math.random() > 0.5 ? 'Heads' : 'Tails';
await new Promise((r) => setTimeout(r, 1000));
}
}
@customElement('my-element')
class MyElement extends LitElement {
@state()
private tosses = tossCoins(10);
render() {
return html`
<ul>${asyncAppend(this.tosses, (v: string) => html`<li>${v}</li>`)}</ul>`;
}
}
async function *tossCoins(count) {
for (let i=0; i<count; i++) {
yield Math.random() > 0.5 ? 'Heads' : 'Tails';
await new Promise((r) => setTimeout(r, 1000));
}
}
class MyElement extends LitElement {
static properties = {
tosses: {state: true},
};
constructor() {
super();
this.tosses = tossCoins(10);
}
render() {
return html`
<ul>${asyncAppend(this.tosses, (v) => html`<li>${v}</li>`)}</ul>`;
}
}
customElements.define('my-element', MyElement);
asyncAppend
については、プレイグラウンドで詳しく調べてください。
asyncReplace
「asyncReplace」へのパーマリンクAsyncIterable
から最新の値が生成されると、DOMにレンダリングします。
インポート |
|
シグネチャ |
|
使用可能な場所 | 任意の式 |
asyncAppend
と同様に、asyncReplace
は、非同期イテラブルの値をレンダリングし、前の値を新しい値でそれぞれ置き換えます。
async function *countDown(count: number) {
while (count > 0) {
yield count--;
await new Promise((r) => setTimeout(r, 1000));
}
}
@customElement('my-element')
class MyElement extends LitElement {
@state()
private timer = countDown(10);
render() {
return html`Timer: <span>${asyncReplace(this.timer)}</span>.`;
}
}
async function *countDown(count) {
while (count > 0) {
yield count--;
await new Promise((r) => setTimeout(r, 1000));
}
}
class MyElement extends LitElement {
static properties = {
timer: {state: true},
};
constructor() {
super();
this.timer = countDown(10);
}
render() {
return html`Timer: <span>${asyncReplace(this.timer)}</span>.`;
}
}
customElements.define('my-element', MyElement);
asyncReplace
については、プレイグラウンドで詳しく調べてください。