今回は、Angular を使用して動的ローディング コンポーネント メソッドを使用して Dialog を実装する方法を説明します。 、見てみましょう。 インターネット上の記事やチュートリアルは、基本的にコンポーネントが読み込まれると終了します。消えた? !また、ダイアログは 1 つしか存在できません。別のダイアログを開きたい場合は、まず現在開いているダイアログを破棄する必要があります。資料の実装を見た後、ソース コードを理解するには愚かであると自分を責めるので、実装することしかできません。 Dialog コンポーネントが利用可能になりました
Dialog コンポーネントの目的: 複数の Dialog が同時に存在でき、指定された Dialog は破棄された後に HTML に残りません。コンポーネントを動的にロードするには 2 つの方法があり、angular4.0 バージョンの ComponentFactoryResolver が実装されるまでは、より便利な ngComponentOutlet を使用して実装できます。 ComponentFactoryResolver
まず、ViewChild、ViewChildren、ElementRef、ViewContainerRef、ViewRef、ComponentRef、ComponentFactoryResolver の関係を整理しましょう:
ViewChild と ViewChildrenViewChild は Angular Dom
抽象クラスを取得するために使用されますテンプレートを通して参照
変数 (#) またはディレクティブ (ディレクティブ) は、ElementRef または ViewContainerRef を使用してカプセル化できます。 @ViewChild('customerRef') customerRef:ElementRef;
@ViewChildren(ChildDirective) viewChildren: QueryList<ChildDirective>;
ElementRef と ViewContainerRefViewChild は、ElementRef または ViewContainerRef を使用してカプセル化できます。では、ElementRef と ViewContainerRef の違いは何でしょうか。
ElementRef を使用してカプセル化してから、.nativeElement を使用してネイティブ Dom 要素を取得します
console.log(this.customerRef.nativeElement.outerHTML);
ViewContainerRef: ビューのコンテナー (ビューの作成方法とビューを操作するための API (コンポーネントとテンプレートを一緒に含む) を含む)ビューを定義します)。 API は ComponentRef と ViewRef を返しますが、これら 2 つは何でしょうか? // 使用ViewContainetRef时,请使用read声明
@ViewChild('customerRef',{read: ViewContainerRef}) customerRef:ViewContainerRef;
···
this.customerRef.createComponent(componentFactory) // componentFactory之后会提到
ViewRef は、ViewContainerRef API が動作し、ViewRef を取得します。ホスト ビュー (コンポーネント インスタンス ビュー) は、ViewContainerRef を通じてコンポーネント ビューへの参照を作成し、コンポーネントのビューを取得できます。情報を取得してコンポーネントのメソッドを呼び出します
ComponentFactoryResolverComponentRef を取得するには、ViewContainer の createComponent メソッドを呼び出す必要があります。このメソッドは、ComponentFactoryResolver
constructor( private componentFactoryResolver:ComponentFactoryResolver ) { } viewInit(){ componentFactory = this.componentFactoryResolver.resolveComponentFactory(DialogComponent); // 获取对组件视图的引用,到这一步就已经完成了组件的动态加载 componentRef = this.customerRef.createComponent(componentFactory); // 调用载入的组件的方法 componentRef.instance.dialogInit(component); }
特定の実装によって作成されたパラメーターを渡す必要があります。
letComponentFactory、componentRef; @ViewChild('customerRef',{read: ViewContainerRef}) customerRef:ViewContainerRef;
constructor(
private componentFactoryResolver:ComponentFactoryResolver
) { }
viewInit(){
// DialogComponent:你想要动态载入的组件,customerRef:动态组件存放的容器
componentFactory =
this.componentFactoryResolver.resolveComponentFactory(DialogComponent);
componentRef = this.customerRef.createComponent(componentFactory);
}
ngComponentOutletを通じて動的ロードを実現
ngComponentOutletはコード量を大幅に削減しますが、4.0以降のバージョンでのみサポートされます
詳細な実装 Dialog.component.html の storage ノード<ng-container *ngComponentOutlet="componentName"></ng-container>
dialogInit(component){
this.componentName = component;
};
ダイアログの実装
実装のアイデアは次のとおりです。まず、他のコンポーネントをホストするダイアログ コンポーネントを作成し、ダイアログのマスクとアニメーションを作成し、ダイアログの生成と破棄を制御するサービスを確立します。ただし、サービスはダイアログを生成するだけです。ダイアログ内のコンポーネントは引き続きダイアログ コンポーネントで生成する必要があります。 1. まず、ルート コンポーネントの viewContainerRef を取得するパブリック サービスを作成します (ルートの viewContainerRef を取得するために ApplicationRef を試しました)。コンポーネントを作成しましたが失敗したので、サービスとして書きました)
gerRootNode(...rootNodeViewContainerRef){ if(rootNode){ return rootNode; }else { rootNode = rootNodeViewContainerRef[0]; }; } // 然后再根组件.ts内调用 this.fn.gerRootNode(this.viewcontainerRef);
2.dialog.service.tsを作成し、openとcloseの3つのメソッドを定義し、ViewContainerRefを使用してダイアログコンポーネントを作成します。作成する前に、ComponentFactoryResloverを呼び出して渡す必要があります。 DialogComponent は
let componentFactory; let componentRef; @Injectable() export class DialogService { constructor( private componentFactoryResolver:ComponentFactoryResolver private fn:FnService ) { } open(component){ componentFactory = this.componentFactoryResolver.resolveComponentFactory(DialogComponent); // 这里的获取的是ComponentRef containerRef = this.fn.gerRootNode().createComponent(componentFactory); // 将containerRef存储下来,以便之后的销毁 containerRefArray.push(containerRef); // 调用了组件内的初始化方法,后面会提到 return containerRef.instance.dialogInit(component,containerRef); } // 这里有两种情况,一种是在当前组件和dialog组件关闭调用的,因为有返回值所以可以关闭指定的dialog;还有一种是在插入到dialog组件内的组件调用的,因为不知道父组件的信息,所以默认关闭最后一个dialog close(_containerRef=null){ if( _containerRef ){ return _containerRef.containerRef.instance.dialogDestory(); }else{ containerRefArray.splice(-1,1)[0].instance.dialogDestory(); } } }
3.dialog.component.ts にあります。ここでは ngComponentOutlet を使用して実装します (ngComponentOutlet については後述しますが、面倒なので直接使用します)
let containerRef,dialogRef = new DialogRef(); export class DialogComponent implements OnInit { componentName; constructor( private fn:FnService ) { } dialogInit( _component, _containerRef){ this.componentName = _component; containerRef = _containerRef; dialogRef['containerRef'] = containerRef; return dialogRef; }; dialogDestory(){ let rootNode = this.fn.gerRootNode(); // 等待动画结束再移除 setTimeout(()=>{ // 这里用到了 viewContainerRef 里的indexOf 和 remove 方法 rootNode.remove(rootNode.indexOf(containerRef.hostView)); },400); dialogRef.close(); return true; }; }
4、这里还创建了一个 DialogRef 的类,用来处理 dialog 关闭后的回调,这样就可以使用 XX.afterClose().subscribe() 来创建回调的方法了
@Injectable() export class DialogRef{ public afterClose$ = new Subject(); constructor(){} close(){ this.afterClose$.next(); this.afterClose$.complete(); } afterClose(){ return this.afterClose$.asObservable(); } }
创建和销毁dialog
// 创建 let _viewRef = this.dialogService.open(DialogTestComponent); _viewRef.afterClose().subscribe(()=>{ console.log('hi'); }); // 销毁 this.dialogService.close()
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
以上がAngular を使用して動的読み込みコンポーネントメソッドを使用してダイアログを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。