이번에는 Angular를 사용하여 동적 로딩 컴포넌트 방식을 사용하여 Dialog를 구현하는 방법을 보여드리겠습니다. 동적 로딩 컴포넌트 방식을 사용하여 Dialog를 구현하기 위해 Angular를 실행할 때 주의할 점은 무엇입니까? , 살펴 보겠습니다.
인터넷의 기사와 튜토리얼은 기본적으로 구성 요소가 로드되면 끝납니다! 다 쓴? ! 그리고 대화상자는 하나만 있을 수 있는데, 또 다른 대화상자를 열려면 현재 열려 있는 대화상자를 먼저 파기해야 합니다. 이제 대화 상자 구성 요소를 사용할 수 있습니다.대화 상자 구성 요소의 목표: 여러 개의 대화 상자가 동시에 존재할 수 있으며 지정된 대화 상자가 파괴된 후에는 구성 요소가 HTML에 남아 있지 않습니다. Angular4.0 버전 ComponentFactoryResolver가 구현되기 전에 사용되었던 컴포넌트를 동적으로 로드하는 방법이 두 가지 있습니다. 4.0 이후에는 ngComponentOutlet을 사용하여 구현할 수 있습니다. ComponentFactoryResolver먼저 ViewChild, ViewChildren, ElementRef, ViewContainerRef, ViewRef, ComponentRef 및 ComponentFactoryResolver 간의 관계를 정리하겠습니다.
ViewChild 및 ViewChildren
ViewChild는 템플릿 참조 변수를 통해 Angular Dom
추상 클래스를 얻는 데 사용됩니다. ( #) 또는 지시문(지시문). ViewChild는 ElementRef 또는 ViewContainerRef를 사용하여 캡슐화할 수 있습니다.
@ViewChild('customerRef') customerRef:ElementRef;ViewChildren은 여러 ViewChild로 구성된 배열과 같은 템플릿 참조 변수 또는 명령어를 통해 QueryList를 얻는 데 사용됩니다.
@ViewChildren(ChildDirective) viewChildren: QueryList<ChildDirective>;
ElementRef 및 ViewContainerRef
ViewChild는 ElementRef 또는 ViewContainerRef를 사용하여 캡슐화할 수 있습니다. 그렇다면 ElementRef와 ViewContainerRef의 차이점은 무엇인가요?
ElementRef를 사용하여 캡슐화한 다음 .nativeElement를 사용하여 기본 Dom 요소를 가져옵니다.console.log(this.customerRef.nativeElement.outerHTML);ViewContainerRef: 뷰를 생성하는 방법과 뷰를 작동하기 위한 API를 포함하는 뷰의 컨테이너(컴포넌트와 템플릿이 공동으로) 뷰를 정의합니다.) API는 ComponentRef와 ViewRef를 반환하는데, 이 두 가지는 무엇입니까?
// 使用ViewContainetRef时,请使用read声明 @ViewChild('customerRef',{read: ViewContainerRef}) customerRef:ViewContainerRef; ··· this.customerRef.createComponent(componentFactory) // componentFactory之后会提到
ViewRef 및 ComponentRef
ViewRef는 가장 작은 UI 단위입니다. ViewContainerRef API가 작동하여 ViewRef를 얻습니다.
ComponentRef: 호스트 뷰(컴포넌트 인스턴스 뷰)는 ViewContainerRef를 통해 컴포넌트 뷰에 대한 참조를 생성하고 해당 컴포넌트의 뷰를 얻을 수 있습니다. 정보 및 구성요소 메소드 호출ComponentFactoryResolver
ComponentRef를 얻으려면 ViewContainer의 createComponent 메소드를 호출해야 합니다. 이 메소드는 ComponentFactoryResolver
constructor( private componentFactoryResolver:ComponentFactoryResolver ) { } viewInit(){ componentFactory = this.componentFactoryResolver.resolveComponentFactory(DialogComponent); // 获取对组件视图的引用,到这一步就已经完成了组件的动态加载 componentRef = this.customerRef.createComponent(componentFactory); // 调用载入的组件的方法 componentRef.instance.dialogInit(component); }특정 구현
에서 생성된 매개변수를 전달해야 합니다. componentFactory, 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를 통한 동적로드는 코드의 양을 크게 줄입니다. Dialog.comComponent.html<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를 만들고, 열기 및 닫기의 세 가지 메서드를 정의하고, ViewContainerRef를 사용하여 대화 상자 구성 요소를 생성하기 전에 ComponentFactoryReslover를 호출하고 전달해야 합니다.
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.comComponent.ts의 DialogComponent, 여기서는 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를 사용하여 동적 로딩 컴포넌트 메소드를 사용하여 Dialog를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!