以前、ネイティブ API の動的ビュー挿入を紹介しましたが、この関数はすでにほとんどの使用シナリオに対応できます。ただし、Angular アプリケーションの外部にコンテンツを挿入する必要性はまだ解決されておらず、命令では動的に挿入されたコンポーネントと入出力の対話を行うことができません。
幸いなことに、Angular は、動的ビューの作成を支援する「ポータル」を含む、さまざまな Angular コンポーネントを開発するための基本ツールとして、コンポーネント開発キットのセットであるコンポーネント開発キット (CDK) を公式に提供しています。 。
この「動的ビュー」は、3 つのポータル タイプ (ComponentPortal、TemplatePortal、DomPortal) に対応するコンポーネント、TemplateRef、または DOM 要素にすることができます。これら 3 つの抽象汎用基本クラスは Portal<T>
で、これには 3 つのメソッドがあります:attach (コンテナーにマウント)、detach (コンテナーからの削除)、isAttached (ビューが搭載されています))。
コンテナは、ビューと同様の抽象クラス BasePortalOutlet
によっても定義され、アタッチ (ビューをコンテナにマウント)、デタッチ (ビューをコンテナから削除) が含まれます。 、dispose (コンテナを破棄)、isAttached (マウントされたビューがあるかどうか)。その主な実装は DomPortalOutlet
クラスです。 3 種類のダイナミック ビューをマウントするために使用されます。
まず、3 つの動的ビューの作成を見てみましょう。
ComponentPortal
ネイティブ API と比較して、動的コンポーネントの作成は非常に簡単です。コンポーネント クラスを渡すだけです。 ComponentPortal
コンストラクターを使用するだけです。
this.componentPortal = new ComponentPortal(ExampleComponent);
任意のカスタム コンポーネント クラスを渡して ComponentPortal
オブジェクトを作成し、それをビューに動的に挿入できます。
✨注: Angular 9 以降のバージョンには Ivy コンパイラを使用することをお勧めします。古いバージョンのコンパイラの場合は、渡されるコンポーネント クラスを entryComponents## で宣言する必要があります。モジュールの # およびこのモジュール 遅延読み込みはありません。
TemplatePortal
コンポーネントと比較して、TemplatePortal の構築にはパラメーター (ViewContainerRef) が 1 つ増えています。前の記事を読んだ後は、これに精通しているはずですが、埋め込みビューを作成するには、これを利用してcreateEmbeddedView() を呼び出す必要があります。ここでは、コンストラクター インジェクションを通じて、現在のコンポーネントの
ViewContainerRef インスタンスが直接使用されます。
<ng-template #testTemplate> <p>一些需要动态插入的内容.</p> </ng-template>
@ViewChild('testTemplate') templatePortalContent: TemplateRef<any>; constructor(private _viewContainerRef: ViewContainerRef) { } ngAfterViewInit() { this.templatePortal = new TemplatePortal( this.templatePortalContent, this._viewContainerRef ); }
<ng-template cdkPortal> <p>一些需要动态插入的内容.</p> </ng-template> <!-- 或写作 --> <!-- 和上面写法是一致的效果 --> <p *cdkPortal> 一些需要动态插入的内容. </p>
@ViewChild を通じて
TemplatePortal のインスタンスを取得できます。
DomPortal
上記の例と同様に、@ViewChild で Template インスタンスを取得して作成すると、こちらも同様にElementRefを取得して動的DOMを作成します。
<div #domPortalContent><span>原生DOM内容</span></div>
@ViewChild('domPortalContent') domPortalContent: ElementRef<HTMLElement>; ngAfterViewInit() { this.domPortal = new DomPortal(this.domPortalContent); }
CdkPortOutlet
CdkPortOutlet コマンドを渡すのが最も簡単な方法です:<div> <ng-template [cdkPortalOutlet]="anyPortal"></ng-template> </div>
anyPortal 上記 3 つの値のいずれかの Portal インスタンスが現在の位置に動的にレンダリングされます。
attached があり、このイベントを通じて、マウントされたコンポーネント インスタンスまたは TemplateRef を取得できます。これにより、マウントされたコンポーネントとの対話も非常に便利になります。
コンテナ インスタンスの構築
ただし、任意の場所にレンダリングできるとのことなので、当然 Angular アプリケーションの外部も含まれます。 . アプリケーションにレンダリングするには さらに、コンストラクターを通じてコンテナー インスタンスを作成する必要があります。 このコンテナ クラスはDomPortalOutlet で、
PortalOutlet の実装サブクラスです。その構築パラメータは主に次のとおりです: Element (マウントされたビューの DOM ノード)、ComponentFactoryResolver (前の記事と同じ、コンポーネントを動的に構築するために使用されます)、appRef (現在の Angular アプリケーションの全体的なインスタンス)、Injector (インジェクター、依存関係を渡します)。
constructor( private viewContainerRef: ViewContainerRef, @Inject(DOCUMENT) private document: any, private injector: Injector, private componentFactoryResolver: ComponentFactoryResolver ) { // 在<body>下创建外部宿主元素 const container = this.document.createElement('div'); container.classList.add('outside-portal-container'); this.outsideContainer = this.document.body.appendChild(container); // 获取应用实例 this.appRef = this.injector.get(ApplicationRef); // 创建外部容器 this.outsideOutlet = new DomPortalOutlet( this.outsideContainer, this.componentFactoryResolver, this.appRef, this.injector ); } // 在应用外部插入动态组件。 openComponentPortalOutSideAngularContext(): void { const componentPortal = new ComponentPortal(AlertComponent); const componentRef = this.outsideOutlet.attach(componentPortal); componentRef.instance.closeAlert.subscribe(() => { this.outsideOutlet.detach(); }); } // 在应用外部插入动态模板。 openTemplatePortalInsideAngularContext(): void { const templatePortal = new TemplatePortal(this.templatePortalContent, this.viewContainerRef); this.outsideOutlet.attach(templatePortal); }
const injectionToken = new InjectionToken<any>('Sharing data with outside component portal'); const customInjector = Injector.create({ providers: [{ provide: CustomInjectionToken, useValue: 'test value' }] });
// 重点是第四个参数 new DomPortalOutlet(this.outsideContainer, this.componentFactoryResolver, this.appRef, customInjector);
constructor(@Inject(injectionToken) public customData: any) {}
// 重点是第三个参数 new TemplatePortal(this.templatePortalContent, this.viewContainerRef, { customData:'test values' });
外部に挿入されたビュー データを操作する機能;
より便利で柔軟な指示。
これを使用すると、動的コンポーネント コンテナー、ポップアップ ウィンドウ、フローティング メニューを作成したり、ローコード設計プラットフォームを構築したりすることも簡単になります。
プロジェクトのソース コード: https://github.com/locotor/angular-dynamic-view-example
オンラインの例: https://coding-pages-bucket-1575455 - 8137703-14801-541995-1303365836.cos-website.ap-beijing.myqcloud.com/
プログラミング関連の知識の詳細については、プログラミング入門をご覧ください。 !
以上がAngular CDK ポータルを使用して動的コンテンツを作成する方法を段階的に説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。