根据 angular 中的 DOM 状态实例化嵌入的组件 2

Instantiate transcluded components depending on their DOM state in angular 2

常用菜单使用案例

<menu>
    <menu-item1></menu-item1>
    <menu-item2></menu-item2>
    <menu-item3></menu-item3>
</menu>

菜单模板

<div *ngIf="open$ | async">
    <ng-content></ng-content>
</div>

我很惊讶地听到所有 menu-item* 组件( 及其所有子组件 )将被实例化,尽管它们存在于 DOM 和 [=15] =] 组件 *ngIf 状态。即使从未打开菜单,它们的 OnInitAfterViewInit 钩子也会被调用,并且 OnDestroy 永远不会触发,尽管确实从 DOM 中添加 - 删除。这是一个关于此 https://github.com/angular/angular/issues/13921 (there is a plnkr with example) and an issue to angular documentation https://github.com/angular/angular.io/issues/3099.

的已关闭问题

但这个问题仍然存在 - 我怎样才能使菜单项仅在菜单打开时实例化并在关闭时正确销毁?所有挂钩都应仅在与真实 DOM 状态相关时触发。

更新Angular5

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>
@Component({
  selector: 'menu',
  template: `
<div *ngIf="open$ | async">
  <template [ngTemplateOutlet]="templateRef"></template>
</div>
`
})
class MenuComponent {
  @ContentChild(TemplateRef) templateRef:TemplateRef;
}

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

这是一个使用 ngTemplateOutlet 的例子

import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'my-app',
  template: `
    <template #templateRef let-label="label" let-url="url">
      <div><a href="{{url}}">{{label}}</a></div>
    </template>

    <div [ngTemplateOutlet]="templateRef" [ngOutletContext]="menu[0]"></div>
    <div [ngTemplateOutlet]="templateRef" [ngOutletContext]="menu[1]"></div>
  `
})
export class App {
    menu:any = [{
           "id": 1,
           "label": "AngularJS",
           "url": "http:\/\/www.learn-angular.fr\/angularJS"
          }, {
           "id": 2,
           "label": "Angular",
           "url": "http:\/\/www.learn-angular.fr\/angular"
    }];

    constructor() {}
}