对于使用ngAfterViewInit
转换为另一个组件的组件,不会调用<ng-content>
生命周期钩子:
<app-container [showContent]="showContentContainer">
<app-input></app-input>
</app-container>
但是,如果没有<ng-content>
,它就可以正常工作:
<app-input *ngIf="showContent"></app-input>
容器组件定义为:
@Component({
selector: 'app-container',
template: `
<ng-container *ngIf="showContent">
<ng-content></ng-content>
</ng-container>
`
})
export class AppContainerComponent {
@Input()
showContentContainer = false;
@Input()
showContent = false;
}
输入组件定义为:
@Component({
selector: 'app-input',
template: `<input type=text #inputElem />`
})
export class AppInputComponent implements AfterViewInit {
@ViewChild("inputElem")
inputElem: ElementRef<HTMLInputElement>;
ngAfterViewInit() {
console.info("ngAfterViewInit fired!");
this.inputElem.nativeElement.focus();
}
}
在此处查看实时示例:https://stackblitz.com/edit/angular-playground-vqhjuh
答案 0 :(得分:1)
如果检查堆栈闪电的控制台,则会看到在按下任何按钮之前触发了该事件。 我只能想到投影的所有内容都会在您声明的地方进行初始化/构造。
所以在您的示例中,就在这两行之间
<app-container [showContent]="showContentContainer">
{{test()}}
<app-input></app-input>
</app-container>
如果在应用程序容器中添加测试功能,它将立即被调用。因此<app-input>
也将立即构建。由于ngAfterVieWInit只会被调用一次(https://angular.io/guide/lifecycle-hooks),因此已经被调用了。
在AppInputComponent
内添加以下内容有点奇怪
ngOnDestroy() {
console.log('destroy')
}
该组件实际上将立即销毁,并且不再进行初始化(添加构造函数或onInit日志进行检查)。
答案 1 :(得分:1)
这里有两个问题:
<ng-content>
以包括它们的情况下。 (请参阅https://github.com/angular/angular/issues/13921)ngAfterViewInit
不会 not 表示该组件已附加到DOM,只是视图已实例化。 (请参阅https://github.com/angular/angular/issues/13925)在这种情况下,可以通过解决其中一个问题来解决该问题:
在很多情况下,两者都适合。
但是,使用自定义指令很容易处理选项#2,为完整起见,我将在此处包括它:
@Directive({
selector: "[attachedToDom],[detachedFromDom]"
})
export class AppDomAttachedDirective implements AfterViewChecked, OnDestroy {
@Output()
attachedToDom = new EventEmitter();
@Output()
detachedFromDom = new EventEmitter();
constructor(
private elemRef: ElementRef<HTMLElement>
) { }
private wasAttached = false;
private update() {
const isAttached = document.contains(this.elemRef.nativeElement);
if (this.wasAttached !== isAttached) {
this.wasAttached = isAttached;
if (isAttached) {
this.attachedToDom.emit();
} else {
this.detachedFromDom.emit();
}
}
}
ngAfterViewChecked() { this.update(); }
ngOnDestroy() { this.update(); }
}
可以这样使用:
<input type=text
(attachedToDom)="inputElem.focus()"
#inputElem />