デコレータ

デコレータは、クラスの動作を宣言的に注釈付けし、変更するために使用できる関数です。

Litは、要素の登録、リアクティブプロパティとクエリプロパティの定義、イベントハンドラメソッドへのイベントオプションの追加など、宣言的なAPIを有効にするオプションのデコレータセットを提供します。

たとえば、@customElementデコレータと@property()デコレータを使用すると、カスタム要素を登録し、リアクティブプロパティをコンパクトで宣言的な方法で定義できます。

Litは、JavaScriptデコレータの提案の2つの異なるバージョンをサポートしています。 _実験的デコレータ_ と呼ぶTypeScriptでサポートされている初期バージョンと、_標準デコレータ_ と呼ぶ新しい最終バージョンです。

2つの提案の使用方法には、いくつかの小さな違いがあります(標準デコレータでは、多くの場合、accessorキーワードが必要です)。 現時点では本番環境での使用を推奨しているため、コードサンプルは実験的デコレータ用に記述されています。

詳細については、デコレータのバージョンを参照してください。

デコレータ概要詳細情報
@customElementカスタム要素を定義します。定義
@eventOptionsイベントリスナーオプションを追加します。イベント
@propertyパブリックプロパティを定義します。プロパティ
@stateプライベート状態プロパティを定義しますプロパティ
@queryコンポーネントテンプレート内の要素を返すプロパティを定義します。シャドウDOM
@queryAllコンポーネントテンプレート内の要素のリストを返すプロパティを定義します。シャドウDOM
@queryAsyncコンポーネントテンプレート内の要素に解決されるpromiseを返すプロパティを定義します。シャドウDOM
@queryAssignedElements特定のslotに割り当てられた子要素を返すプロパティを定義します。シャドウDOM
@queryAssignedNodes特定のslotに割り当てられた子ノードを返すプロパティを定義します。シャドウDOM

lit/decorators.jsモジュールを介してすべてのLitデコレータをインポートできます

コンポーネントを実行するために必要なコードの量を減らすために、デコレータをコンポーネントコードに個別にインポートできます。 すべてのデコレータは、lit/decorators/<decorator-name>.jsで使用できます。 例えば、

デコレータを使用するには、TypeScriptまたはBabelなどのコンパイラでコードをビルドする必要があります。

将来的にデコレータがブラウザでネイティブにサポートされるようになれば、これは不要になります

TypeScriptは、実験的デコレータと標準デコレータの両方をサポートしています。 最適なコンパイラ出力のために、TypeScript開発者は今のところ実験的デコレータを使用することをお勧めします。 プロジェクトで標準デコレータを使用する必要がある場合、または"useDefineForClassFields": trueを設定する必要がある場合は、標準デコレータへの移行までスキップしてください。

実験的デコレータを使用するには、experimentalDecoratorsコンパイラオプションを有効にする必要があります。

また、useDefineForClassFields設定がfalseであることを確認する必要があります。 これは、targetES2022以上に設定されている場合にのみ必要ですが、これを明示的にfalseに設定することをお勧めします。 これは、プロパティを宣言するときにクラスフィールドの問題を回避するために必要です。

emitDecoratorMetadataの有効化は必須ではなく、推奨されません。

TypeScript実験的デコレータの標準デコレータへの移行

「TypeScript実験的デコレータの標準デコレータへの移行」へのパーマリンク

Litデコレータは、TypeScriptの実験的デコレータモードで標準デコレータ構文(デコレータ付きクラスフィールドにaccessorを使用)をサポートするように設計されています。

これにより、動作を変更せずに、デコレータされたプロパティにaccessorキーワードを追加することから始めて、実験的デコレータから段階的に移行できます。 すべてのデコレータ付きクラスフィールドでaccessorキーワードを使用したら、コンパイラオプションを変更して標準デコレータへの移行を完了できます。

注:accessorキーワードはTypeScript 4.9で導入され、メタデータ付きの標準デコレータにはTypeScript≧5.2が必要です。

Babelは、バージョン7.23以降、@babel/plugin-proposal-decoratorsプラグインを使用して標準デコレータをサポートしています。 BabelはTypeScript実験的デコレータをサポートしていないため、デコレータされたクラスフィールドでaccessorキーワードを使用して、標準デコレータ構文でLitデコレータを使用する必要があります。

これらのBabel設定で@babel/plugin-proposal-decoratorsを追加することにより、デコレータを有効にします

注:Litデコレータは、"version": "2023-05"でのみ機能します。 以前サポートされていた"2018-09"を含む他のバージョンはサポートされていません。

デコレータは、ECMAScript標準に追加するためのステージ3の提案です。 BabelTypeScriptなどのコンパイラはデコレータをサポートしていますが、ブラウザはまだ実装していません。 LitデコレータはBabelとTypeScriptで動作し、ブラウザがネイティブに実装したときにも動作します。

ステージ3とはどういう意味ですか?

これは、仕様テキストが完成し、ブラウザが実装する準備ができていることを意味します。 仕様が複数のブラウザに実装されると、最終ステージであるステージ4に移行し、ECMAScript標準に追加できます。 ステージ3の提案は、実装中に重大な問題が発見された場合にのみ変更されます。

TC39の提案がステージ3に達する前は、コンパイラは以前のバージョンのデコレータ仕様を実装していました。

これらの中で最も注目すべきは、TypeScriptの_実験的デコレータ_であり、Litは開始以来サポートしており、現在使用することをお勧めしています。

Babelは、デコレータプラグインの"version"オプションからわかるように、時間の経過とともにさまざまなバージョンの仕様をサポートしてきました。 以前は、Lit 2はBabelユーザー向けに"2018-09"バージョンをサポートしていましたが、現在は以下で説明する_標準_"2023-05"バージョンに置き換えられました。

_標準デコレータ_ は、ECMAScript / JavaScriptを定義する機関であるTC39でステージ3のコンセンサスに達したデコレータのバージョンです。

標準デコレータは、TypeScriptとBabelでサポートされており、近い将来、ネイティブブラウザでもサポートされる予定です。

標準デコレータと実験的デコレータの最大の違いは、パフォーマンス上の理由から、標準デコレータはデコレータされ、置き換えられるクラスメンバー(フィールド、アクセサー、メソッド)の_種類_ を変更できず、同じ種類のメンバーのみを生成することです。

多くのLitデコレータはアクセサーを生成するため、これはデコレータをクラスフィールドではなくアクセサーに適用する必要があることを意味します。

これを便利にするために、標準デコレータ仕様では、"自動アクセサー"を宣言するためのaccessorキーワードが追加されています。

自動アクセサーは、プライベートフィールドを読み書きするゲッターとセッターのペアを作成します。 デコレータは、これらのゲッターとセッターをラップできます。

実験的デコレータでクラスフィールドで機能するLitデコレータ(@property()@state()@query()など)は、標準デコレータではアクセサーまたは自動アクセサーに適用する必要があります。

標準デコレータのコンパイラ出力は、アクセサ、プライベートストレージ、およびデコレータAPIの一部であるその他のオブジェクトを生成する必要があるため、残念ながら大きくなってしまいます。

そのため、デコレータを使用したいユーザーは、可能な場合は、TypeScriptの実験的なデコレータを今のところ使用することをお勧めします。

Litチームは、将来、標準デコレータをよりコンパクトなコンパイラ出力にコンパイルするために、オプションのLitコンパイラにデコレータ変換を追加することを計画しています。ネイティブブラウザのサポートにより、コンパイラ変換の必要性もなくなります。