Angularのng-template、ng-content、ng-container、および* ngTemplateOutletについて知っておく必要があるすべて

それは、私がオフィスプロジェクトの新機能に取り組むのに忙しかった当時の1つでした。突然、何かが私の注意を引きました:

DOMを調べてngcontentいると、Angularによって要素に適用されているのがわかりました。うーん…最終的なDOMの要素が含まれている場合、どのように使用しますか?その時、私はとの間で混乱しました

私の質問に対する答えを知るために、私はの概念を発見しました。驚いたことに、もありました*ngTemplateOutlet。私は2つの概念について明確にすることを求めて旅を始めましたが、今では4つあり、ほぼ同じように聞こえます。

あなたはこの状況に行ったことがありますか?はいの場合、あなたは正しい場所にいます。それで、それ以上の苦労なしに、それらを一つずつ取りましょう。

1.1。

名前が示すように、テンプレート要素があるという構造的なディレクティブと角度の用途(*ngIf*ngFor[ngSwitch]およびカスタムディレクティブ)。

これらのテンプレート要素は、構造ディレクティブが存在する場合にのみ機能します。Angularは、(ディレクティブが適用される)ホスト要素を内部でラップし、診断コメントで置き換えることにより、完成したDOMでを消費します。

の簡単な例を考えてみましょう*ngIf

上に示されているのは、の角度解釈です*ngIf。Angularは、ディレクティブが適用されるホスト要素を配置し、ホストをそのまま維持します。最終的なDOMは、この記事の冒頭で見たものと似ています。

使用法:

Angularがどのように使用されるかを見てきましたが、使用したい場合はどうでしょうか?これらの要素は構造ディレクティブでのみ機能するため、次のように記述できます。

これhomeは、valueにboolean設定されたコンポーネントのプロパティtrueです。DOMでの上記のコードの出力:

何もレンダリングされませんでした!:(

しかし、構造ディレクティブで正しく使用した後でも、メッセージが表示されないのはなぜですか?

これは期待された結果でした。すでに説明したように、Angularはを診断コメントに置き換えます。Angularはユースケースに完全に対応しているため、上記のコードでエラーが発生しないことは間違いありません。舞台裏で何が起こったのかを正確に知ることは決してできません。

Angularによってレンダリングされた上記の2つのDOMを比較してみましょう。

よく見ると、例2の最後のDOMにコメントタグが1つ追加されています。Angularが解釈したコードは次のとおりです。

Angularはホストを別のホストにラップし、外側のコメントだけでなく内側のコメントにも変換しました。これが、メッセージが表示されなかった理由です。

これを取り除くには、希望する結果を得る2つの方法があります。

方法1:

この方法では、Angularに追加の処理を必要としない脱糖フォーマットを提供します。今回、Angularはコメントに変換するだけで、その中のコンテンツは変更されません(前の場合のように、どのコンテンツにも含まれなくなります)。したがって、コンテンツが正しくレンダリングされます。

この形式を他の構造ディレクティブで使用する方法の詳細については、この記事を参照してください。

方法2:

これは非常に目に見えない形式であり、ほとんど使用されません(2人の兄弟を使用)。ここでは、へのテンプレートの参照を与えている*ngIfのではthen条件が真である場合に使用すべきテンプレートにそれを伝えるために。

このように複数を使用することはお勧めできません(代わりに使用できます)。これは意図されたものではないためです。これらは、複数の場所で再利用できるテンプレートのコンテナとして使用されます。これについては、この記事の後のセクションで詳しく説明します。

2.2。

これに似たコードを書いたり見たりしたことがありますか。

私たちの多くがこのコードを書く理由は、Angularの単一のホスト要素で複数の構造ディレクティブを使用できないためです。現在、このコードは正常に機能しますが、が必要ではない可能性のある偽の値である場合、DOMにいくつかの余分な空が導入されitem.idます。

このような単純な例は気にしないかもしれませんが、複雑なDOM(数万のデータを表示する)を持つ巨大なアプリケーションの場合、要素にリスナーがアタッチされている可能性があるため、これは厄介になる可能性があります。イベントをリッスンするDOM。

さらに悪いのは、スタイリング(CSS)を適用するために必要なネストのレベルです。

心配いりません、私たちは救助しなければなりません!

Angularは、スタイルやレイアウトに干渉しないグループ化要素です。AngularはそれをDOMに配置しないためです。

したがって、例1次のように記述した場合:

最終的なDOMは次のようになります。

それらの空のを取り除いたのを見てください。DOMに余分な要素を導入せずに、複数の構造ディレクティブを適用する場合に使用する必要があります。

詳細については、ドキュメントを参照してください。テンプレートを動的にページに挿入するために使用される別のユースケースがあります。このユースケースについては、この記事の最後のセクションで説明します。

3.3。

これらは、構成可能なコンポーネントを作成するために使用されます。これは、ユーザーのニーズに応じてコンポーネントを構成できることを意味します。これは、コンテンツプロジェクションとしてよく知られています。公開されたライブラリで使用されるコンポーネントは、それ自体を構成可能にするために利用されます。

単純なコンポーネントについて考えてみましょう。

コンポーネントの開始タグと終了タグ内で渡されるHTMLコンテンツは、投影されるコンテンツです。これは、コンテンツプロジェクションと呼ばれるものです。コンテンツはコンポーネント内にレンダリングされます。これにより、コンポーネントのコンシューマーは、コンポーネント内のカスタムフッターを渡し、レンダリング方法を正確に制御できます。

複数の予測:

どのコンテンツをどこに配置するかを決めることができたらどうでしょうか。単一の内部に投影されるすべてのコンテンツの代わりにselect属性を使用してコンテンツを投影する方法を制御することもできます。特定の内部に投影するコンテンツを決定するには、要素セレクターが必要です。

方法は次のとおりです。

マルチコンテンツプロジェクションを実行するように定義を変更しました。このselect属性は、特定の内部にレンダリングされるコンテンツのタイプを選択します。ここでは、最初selectにヘッダーh1要素をレンダリングする必要があります。投影されたコンテンツにh1要素がない場合、何もレンダリングされません。同様に、2番目selectはを探しdivます。残りのコンテンツは、最後のコンテンツの中に。なしでレンダリングされますselect

コンポーネントの呼び出しは次のようになります。

4. * ngTemplateOutlet

…複数の場所で再利用できるテンプレートのコンテナとして使用されます。これについては、この記事の後のセクションで詳しく説明します。

…テンプレートをページに動的に挿入するために使用される別のユースケースがあります。このユースケースについては、この記事の最後のセクションで説明します。

これは、前述の2つのポイントについて説明するセクションです。*ngTemplateOutletは、ループや条件に関係なく、ビューのさまざまなセクションに共通のテンプレートを挿入するためと、高度に構成されたコンポーネントを作成するための2つのシナリオで使用されます。

テンプレートの再利用:

複数の場所にテンプレートを挿入する必要があるビューについて考えてみます。たとえば、Webサイト内に配置される会社のロゴ。ロゴのテンプレートを一度作成して、ビュー内のあらゆる場所で再利用することで、これを実現できます。

コードスニペットは次のとおりです。

ご覧のとおり、ロゴテンプレートを1回作成し、同じページで1行のコードで3回使用しました。

*ngTemplateOutletまた、共通のテンプレート出力をカスタマイズするために渡すことができるコンテキストオブジェクトも受け入れます。コンテキストオブジェクトの詳細については、公式ドキュメントを参照してください。

カスタマイズ可能なコンポーネント:

の2番目の使用例*ngTemplateOutletは、高度にカスタマイズされたコンポーネントです。いくつかの変更を加えたコンポーネントの前の例を考えてみましょう。

上記の修正版である3つの入力特性を受け付けるコンポーネント- 、  headerTemplate、。bodyTemplate footerTemplate以下はのスニペットですproject-content.ts

ここで達成しようとしているのは、の親コンポーネントから受け取ったヘッダー、本文、およびフッターを表示することです。それらのいずれかが提供されていない場合、コンポーネントはその場所にデフォルトのテンプレートを表示します。したがって、高度にカスタマイズされたコンポーネントを作成します。

最近変更されたコンポーネントを使用するには:

これが、テンプレート参照をコンポーネントに渡す方法です。それらのいずれかが渡されない場合、コンポーネントはデフォルトのテンプレートをレンダリングします。

ng-contentと* ngTemplateOutlet

どちらも高度にカスタマイズされたコンポーネントを実現するのに役立ちますが、どちらをいつ選択するのですか?

*ngTemplateOutlet何も提供されていない場合、デフォルトのテンプレートを表示する能力がさらに向上することがはっきりとわかります。

これは、の場合には当てはまりませんng-content。コンテンツをそのままレンダリングします。最大で、select属性を使用してコンテンツを分割し、ビューのさまざまな場所にレンダリングできます。内のコンテンツを条件付きでレンダリングすることはできませんng-content。親から受け取ったコンテンツを表示する必要があり、コンテンツに基づいて決定を下す手段はありません。

ただし、2つから選択するかどうかは、ユースケースによって異なります。少なくとも今では、!*ngTemplateOutletの機能に加えて、コンテンツをより細かく制御できる新しい武器が武器庫にありますng-content