根据角度2中的DOM状态实例化已转换的组件

dro*_*row 11 angular2-ngcontent angular

常用菜单用例

<menu>
    <menu-item1></menu-item1>
    <menu-item2></menu-item2>
    <menu-item3></menu-item3>
</menu>
Run Code Online (Sandbox Code Playgroud)

菜单模板

<div *ngIf="open$ | async">
    <ng-content></ng-content>
</div>
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,尽管存在于DOM和组件状态,但所有menu-item*组件(及其所有子组件)都将被实例化.即使菜单从未打开过,它们和钩子也会被调用,尽管从DOM中真正添加了删除功能,但它们永远不会触发.这是关于这个https://github.com/angular/angular/issues/13921的封闭式问题(有一个示例的plnkr)和角度文档的问题https://github.com/angular/angular.io/问题/ 3099.menu*ngIfOnInitAfterViewInitOnDestroy

但是这个问题仍然存在 - 我怎么能这样菜单项只有在打开菜单并在关闭后正确销毁时才会被实例化?所有钩子都应该仅与真实DOM状态相关.

Gün*_*uer 6

更新Angular 5

ngOutletContext 被重命名为 ngTemplateOutletContext

另见https://github.com/angular/angular/blob/master/CHANGELOG.md#500-beta5-2017-08-29

原版的

您可以使用

<menu>
  <template>
    <menu-item1></menu-item1>
    <menu-item2></menu-item2>
    <menu-item3></menu-item3>
  <template>
</menu>
Run Code Online (Sandbox Code Playgroud)
@Component({
  selector: 'menu',
  template: `
<div *ngIf="open$ | async">
  <template [ngTemplateOutlet]="templateRef"></template>
</div>
`
})
class MenuComponent {
  @ContentChild(TemplateRef) templateRef:TemplateRef;
}
Run Code Online (Sandbox Code Playgroud)

你也可以传递上下文ngTemplateOutlet(有一些答案显示如何做到这一点,我没有时间只是不去查找它们)

  • 在阅读了有关该主题的所有相关信息后,我觉得这种意想不到的行为非常令人失望。Angular 团队可以说:“这是设计使然”,但 Angular 文档中没有明确或明确的说法。我确信有成千上万的 Angular 用户认为 ngIf 在任何地方都一样工作,并在 ngOnInit() 中实现了很多逻辑,正如 Angular 指南所说,这是某种矛盾。只是咆哮,感谢冈特的解决方法! (2认同)