0

我有一个这样的父组件。所以菜单中的项目数量取决于型号。和模型的变化。

<parent>
<menu>
  <item *ngIf="model.info">
   ... some data
  <item *ngIf="model.comments">
  .... some data 
  <item *ngIf="model.attachments">
   ... some data
  <item *ngIf="model.orders">
  .... some data
 </menu>
</parent>

父组件:

 export class Parent {
   @Input() public model: any;
 }   

如果菜单本身是一个使用 ng-content 的组件,我正在根据 menuItems 计数创建菜单。

selector: 'menu',
template: ` <ul class="nav"
    <li *ngFor="let item of items"  [class.active]="item.active"
    <a class="btn" (click)="menuItemClicked(item)"> </a>
    </li>
    </ul>

  <div class="content">
     <ng-content></ng-content>
  </div>

`
export class MenuComponent  {
  @ContentChildren(MenuItem) items;

  ngAfterContentInit() {
     this.setActiveMenuItem();
  }

  public menuItemClicked(item) {
    this.changeActiveItem(item)
  }


  private setActiveItem() {
      const items = this.items.toArray();
      const actives = this.items.filter(i => i.active);

      if (!actives.length && items.length) {
         items[0].active = true;
      }
  }

  private changeActiveItem(item) {
      const items = this.items.toArray();
      items.forEach(i => i.active = false);
      item.active = true;
  }

}

其中单个 menuItem 本身是一个组件,它使用 ng-content:

@Component({
selector: 'item',
template: `
   <ng-content *ngIf="active"></ng-content>
`
})
export class MenuItemComponent {
  @Input() active = false;

  public setActive() {
    this.active = true;
  }

  public setNotActive() {
    this.active = false;
  }

}

父组件是这样使用的:

<app>
    <parent *ngIf="model.displayMenu" [model]="model"></parent>
</app>

所以它只创建一次,然后根据用户操作(点击等)进行模型更改

现在有什么问题?问题是假设我已经创建了一个父组件。在我的用例模型中发生了变化。我确切地知道模型何时更改,但问题是在该更改中我希望始终第一个菜单项在该更改中处于活动状态。

我的问题是我无法使用 ngAfterViewInit 钩子,因为这些项目还不存在。角度变化检测需要一些时间来更改该内容。如果我使用 ngAfterViewInit,菜单项还没有在那个钩子中更新。我不想使用 ngAfterViewChecked,因为它会不断触发更改检测并导致性能问题(在模型信息中存在不断变化的流的背后)。

示例:我有活动的第 4 个菜单项和模型更改。下一个模型只有 2 个菜单项,我希望菜单项顺利切换到第一个菜单项。如果我不这样做,那么我会得到空内容。

这怎么可能解决?

4

1 回答 1

0

您可以简单地使用 setter 实现您的 ContentChildren:

items: QueryList<MenuItem>;

@ContentChildren(MenuItem) 
set menuItems(items) {
    this.items = items;
    this.setActiveMenuItem();
}

menuItems-setter 在 contenchildren 更改时被调用。

希望这有帮助,我正确理解了您的问题。

于 2018-03-08T16:00:20.723 回答