13

常见菜单使用案例

<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 和menu组件*ngIf状态中。即使菜单从未打开过,它们的OnInit和钩子也会被调用,并且即使从 DOM 中真正添加-删除也不会触发。这是关于此https://github.com/angular/angular/issues/13921的已关闭问题(有一个带有示例的 plnkr)和角度文档的问题https://github.com/angular/angular.io/问题/3099AfterViewInitOnDestroy

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

4

2 回答 2

8

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

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

于 2017-01-14T22:15:45.800 回答
0

这是一个使用 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() {}
}
于 2017-01-16T13:51:27.610 回答