假设我有这样的html:
<div *ngIf="(isVisible | async)">
<app-mycomponent></app-mycomponent>
</div>
<div *ngIf="!(isVisible | async)">
<app-mycomponent></app-mycomponent>
</div>
带有可切换isVisible的按钮。每当我切换可见性时,都会创建一个新的组件实例。
所以我的问题是:切换可见性时,我可以更改实现以使用相同的AppMyComponent实例。例如。通过具有可动态添加app-mycomponent的包装器组件或其他方式。
编辑:我的实际情况非常复杂,即使这个示例没有意义,我对此也很感兴趣。
EDIT2:这是stackbliz,可以解决我的问题。
答案 0 :(得分:4)
此答案基于此stackblitz example中提供的answer,与我提出的类似问题相同。
第1步:创建一个指令,该指令将在您希望拥有可重用组件的任何地方使用。
@Directive({
selector: '[reusable-outlet]',
})
export class ReusableDirective implements OnInit {
constructor(
private viewContainerRef: ViewContainerRef,
private reusableService: ReusableService
) { }
public ngOnInit(): void {
this.reusableService.attach(this.viewContainerRef);
}
}
步骤2 创建将负责以下服务的服务:
注意:知道何时分离组件是基于路由器事件的,但是,如果您需要更改组件的位置而不进行导航更改,则应该可以基于消息来代替它。
@Injectable()
export class ReusableService {
private componentRef: ComponentRef<ReusableComponent>;
private currentViewContainerRef: ViewContainerRef;
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private injector: Injector,
private router: Router
) {
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(ReusableComponent);
this.componentRef = componentFactory.create(injector);
this.router.events.subscribe(event => {
if (event instanceof NavigationStart && this.currentViewContainerRef) {
this.detach(this.currentViewContainerRef);
}
});
}
public attach(viewContainerRef: ViewContainerRef) {
this.currentViewContainerRef = viewContainerRef;
viewContainerRef.insert(this.componentRef.hostView);
}
public detach(viewContainerRef: ViewContainerRef) {
viewContainerRef.detach(viewContainerRef.indexOf(this.componentRef.hostView));
}
}
答案 1 :(得分:0)
1)在#dynamicComponentContainer
中插入视图。
2)我们可以跟踪变量或对象中的组件或所有组件并销毁它们:-
3)或者,在存储DOM中的新组件时,通过存储最后一个引用并在插入新组件之前.destroy()
来销毁上一个组件。
<ng-container #dynamicComponentContainer id="dynamicComponentContainer"></ng-container>
public loadComponent(cmptName){
switch (cmptName) {
case 'abcComponent':
cmptName = abcComponent;
break;
case 'cdeComponent':
cmptName = cdeComponent;
break;
}
let componentRef = this.componentFactoryResolver.resolveComponentFactory(cmptName).create(this.injector);
// check for duplicates and update with new one
// this.checkForDuplicateCmp(componentRef);
// send data to respecting component using `inputdata`
componentRef.instance['inputdata'] = initCmpInputdata;
let indexView = this.dynamicComponentContainer.length;
this.dynamicComponentContainer.insert(componentRef.hostView, indexView);
// keep reference of lastComponent added to DOM
this.lastComponent = componentRef;
}
public remove component(){
// destroy components as on click
this.lastComponent.destroy();
//or
//for (var j = 1; j < this.dynamicComponentContainer.length; j++) {
// this.dynamicComponentContainer.remove(j); //or pass j
// }
// }
@Input() inputdata: any;
注意:-对于abccomoponent调用的多个实例
loadComponent(abccomoponent )