ホームページ > 記事 > ウェブフロントエンド > Angular は動的読み込みコンポーネント メソッドを使用してダイアログ ステップを実装します。詳細な説明
今回は、Angular が動的読み込みコンポーネント メソッドを使用して Dialog を実装するための手順について詳しく説明します。 Angular が動的読み込みコンポーネント メソッドを使用して Dialog を実装するための 注意事項 は次のとおりです。ケース、見てみましょう。
インターネット上の記事やチュートリアルは、基本的にコンポーネントが読み込まれると終了します。消えた? !また、ダイアログは 1 つしか存在できません。別のダイアログを開きたい場合は、まず現在開いているダイアログを破棄する必要があります。資料の実装を見た後、ソース コードを理解するには愚かであると自分を責めるので、実装することしかできません。ダイアログ コンポーネントが利用可能になりました ダイアログ コンポーネントの目的: 複数のダイアログを同時に存在でき、指定されたダイアログは破棄後に HTML に残り、コールバックは削除されます。コンポーネントを動的にロードするには 2 つの方法があり、angular4.0 バージョンの ComponentFactoryResolver が実装される前に使用されていました。4.0 以降は、より便利な ngComponentOutlet を使用してコンポーネントを動的にロードできます 。まず、ViewChild、ViewChildren、ElementRef、ViewContainerRef、ViewRef、ComponentRef、ComponentFactoryResolver の関係を整理しましょう:ViewChild と ViewChildren
ViewChild は、テンプレート参照変数
を通じて Angular Dom抽象クラス を取得するために使用されます ( #) またはディレクティブ (ディレクティブ) は、ElementRef または ViewContainerRef を使用してカプセル化できます。
@ViewChild('customerRef') customerRef:ElementRef;ViewChildren は、複数の ViewChild で構成される配列などのテンプレート参照変数または命令を通じて QueryList を取得するために使用されます。
@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 と ComponentRef
ViewRef は、ViewContainerRef API が操作して取得するのは ViewRefComponentRef です。ホスト ビュー (コンポーネント インスタンス ビュー) は、ViewContainerRef を通じてコンポーネント ビューへの参照を作成します。コンポーネントの情報を取得し、コンポーネントのメソッドを呼び出しますComponentFactoryResolver
ComponentRefを取得するには、ViewContainerのcreateComponentメソッドを呼び出す必要があります。このメソッドは、ComponentFactoryResolverconstructor( private componentFactoryResolver:ComponentFactoryResolver ) { } viewInit(){ componentFactory = this.componentFactoryResolver.resolveComponentFactory(DialogComponent); // 获取对组件视图的引用,到这一步就已经完成了组件的动态加载 componentRef = this.customerRef.createComponent(componentFactory); // 调用载入的组件的方法 componentRef.instance.dialogInit(component); }
Specificによって作成されたパラメータを渡す必要があります。実装
letコンポーネントFactory、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)<ng-container *ngComponentOutlet="componentName"></ng-container>コンポーネント (コンポーネント名ではなく) を渡すだけでOKです。なぜこんなに簡単なのでしょうか。
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 サイトの他の関連記事を参照してください。