Maison  >  Article  >  interface Web  >  Angular utilise la méthode des composants de chargement dynamique pour implémenter l'explication détaillée des étapes de dialogue

Angular utilise la méthode des composants de chargement dynamique pour implémenter l'explication détaillée des étapes de dialogue

php中世界最好的语言
php中世界最好的语言original
2018-05-22 10:43:462126parcourir

Cette fois, je vais vous apporter une explication détaillée des étapes à suivre pour qu'Angular utilise la méthode du composant de chargement dynamique pour implémenter Dialog. Quelles sont les précautions pour qu'Angular utilise la méthode du composant de chargement dynamique pour implémenter Dialog. . Ce qui suit est un cas pratique, jetons un coup d'œil.

Les articles et tutoriels en ligne se terminent essentiellement lorsque le composant est chargé ! Disparu? ! Et il ne peut y avoir qu'une seule boîte de dialogue. Si vous souhaitez ouvrir une autre boîte de dialogue, vous devez d'abord détruire la boîte de dialogue actuellement ouverte. Après avoir vu l'implémentation du matériel, je me reproche d'être trop stupide pour comprendre le code source, je ne peux donc que l'implémenter. à ma manière. Le composant dialog est

Le but du composant Dialog : plusieurs Dialogs peuvent exister en même temps, et le Dialog spécifié peut être détruit. Après destruction, aucun composant ne reste dans le HTML et. des rappels sont fournis

Il existe deux façons de charger dynamiquement des composants Avant la version angulaire 4.0, ComponentFactoryResolver était utilisé pour l'implémenter. Après angulaire 4.0, le ngComponentOutlet plus pratique peut être utilisé pour l'implémenter

. Le chargement dynamique est réalisé via ComponentFactoryResolver

Tout d'abord, trions la relation entre ViewChild, ViewChildren, ElementRef, ViewContainerRef, ViewRef, ComponentRef et ComponentFactoryResolver :

ViewChild et ViewChildren

ViewChild est référencé via des modèles La variable (#) ou la directive (directive) est utilisée pour obtenir Angular Dom classe abstraite . ViewChild peut être encapsulé en utilisant ElementRef ou ViewContainerRef.

@ViewChild('customerRef') customerRef:ElementRef;

ViewChildren est utilisé pour obtenir QueryList via des variables ou des instructions de référence de modèle, comme un tableau composé de plusieurs ViewChilds.

@ViewChildren(ChildDirective) viewChildren: QueryList<ChildDirective>;

ElementRef et ViewContainerRef

ViewChild peuvent être encapsulés à l'aide d'ElementRef ou ViewContainerRef Alors, quelle est la différence entre ElementRef et ViewContainerRef ?

Encapsulez-le avec ElementRef, puis obtenez l'élément Dom natif via .nativeElement

console.log(this.customerRef.nativeElement.outerHTML);

ViewContainerRef : le conteneur de la vue, y compris la méthode de création de la vue et l'API pour son fonctionnement la vue (commune aux composants et aux modèles) définie). L'API renverra ComponentRef et ViewRef, alors quels sont ces deux-là ?

// 使用ViewContainetRef时,请使用read声明
@ViewChild('customerRef',{read: ViewContainerRef}) customerRef:ViewContainerRef;
···
this.customerRef.createComponent(componentFactory) // componentFactory之后会提到

ViewRef et ComponentRef

ViewRef est la plus petite unité d'interface utilisateur. Ce que l'API ViewContainerRef exploite et obtient est ViewRef

ComponentRef : vue hôte. (Vue de l'instance du composant) Grâce à la référence à la vue du composant créée par ViewContainerRef, vous pouvez obtenir les informations sur le composant et appeler la méthode du composant

ComponentFactoryResolver

Pour obtenir le ComponentRef , vous devez appeler ViewContainer. La méthode createComponent doit transmettre les paramètres créés par ComponentFactoryResolver

constructor(
 private componentFactoryResolver:ComponentFactoryResolver
) { }
viewInit(){
  componentFactory = 
   this.componentFactoryResolver.resolveComponentFactory(DialogComponent);
  // 获取对组件视图的引用,到这一步就已经完成了组件的动态加载
  componentRef = this.customerRef.createComponent(componentFactory);
  // 调用载入的组件的方法
  componentRef.instance.dialogInit(component);
}

L'implémentation spécifique

let composantFactory ,componentRef;

@ViewChild('customerRef',{read: ViewContainerRef}) customerRef:ViewContainerRef;
constructor(
 private componentFactoryResolver:ComponentFactoryResolver
) { }
viewInit(){
 // DialogComponent:你想要动态载入的组件,customerRef:动态组件存放的容器
  componentFactory = 
   this.componentFactoryResolver.resolveComponentFactory(DialogComponent);
  componentRef = this.customerRef.createComponent(componentFactory);
}

Réaliser un chargement dynamique via ngComponentOutlet

ngComponentOutlet réduit considérablement la quantité de code, mais il n'est pris en charge que par les versions après 4.0

Implémentation spécifique

Créer un nœud de stockage de composants dynamiques dans dialog.component.html

<ng-container *ngComponentOutlet="componentName"></ng-container>

Passez le composant (pas le nom du composant) et tout ira bien. Pourquoi cela peut être aussi simple !

dialogInit(component){
  this.componentName = component;
};

Implémentation de dialogue

L'idée d'implémentation est la suivante : créez d'abord un composant de dialogue pour héberger d'autres composants, par exemple la boîte de dialogue Créez des masques et des animations et créez un service pour contrôler la génération et la destruction de la boîte de dialogue. Cependant, le service génère uniquement la boîte de dialogue. Les composants de la boîte de dialogue doivent encore être générés dans le composant de boîte de dialogue

. 1. Écrivez d'abord un service public. Utilisé pour obtenir le viewContainerRef du composant racine (j'ai essayé ApplicationRef pour obtenir le viewContainerRef du composant racine mais j'ai échoué, je l'ai donc écrit en tant que service)

gerRootNode(...rootNodeViewContainerRef){
  if(rootNode){
   return rootNode;
  }else {
   rootNode = rootNodeViewContainerRef[0];
  };
}
// 然后再根组件.ts内调用
this.fn.gerRootNode(this.viewcontainerRef);

2. Créez dialog.service.ts et définissez trois méthodes : open et close. , utilisez ViewContainerRef pour créer le composant de dialogue. Avant la création, vous devez appeler ComponentFactoryReslover et transmettre le DialogComponent dans la boîte de dialogue

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. composant.ts. Utilisez ngComponentOutlet pour l'implémenter ici (ngComponentOutlet est mentionné ci-dessous, juste pour être paresseux. , utilisé directement)

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中文网其它相关文章!

推荐阅读:

Node.js Express安装与使用步骤详解

table表格内对某列内容进行搜索筛选步骤详解

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn