8

我的影片由兩個部分組成的遞歸結構:使用angular2組件實現遞歸結構(不帶forwardRef)?

  • OptionsMenuComponent(菜單)
  • MenuItemComponent(菜單項)

OptionsMenuComponent:(模板+組件)

Template: 
    <menu-item *ngFor="let menuItem of menu.menuItems" [menuItem]="menuItem"> </menu-item> 

Component: 
    import { Component, Input } from '@angular/core'; 
    import { Menu } from '../models/menu.model'; 
    import { MenuItemComponent } from '../menu-item/menu-item.component'; 

    @Component({ 
     moduleId: __moduleName, 
     selector: 'options-menu', 
     templateUrl: 'options-menu.component.html', 
     styleUrls: ['options-menu.component.css'], 
     directives: [MenuItemComponent], 
    }) 
    export class OptionsMenuComponent { 
     @Input() menu: Menu; 

     constructor() { } 
    } 

菜單項:(模板+組件)

Template: 
    <span class="menu-item-title">{{menuItem.title}}</span> 

    <options-menu *ngIf="menuItem.subMenu != null" [menu]="menuItem.subMenu" class="sub-menu"> </options-menu> 

Component: 
    import { Component, Input, forwardRef } from '@angular/core'; 
    import { MenuItem } from '../models/menu-item.model'; 
    import { OptionsMenuComponent } from '../options-menu/options-menu.component'; 

    @Component({ 
     moduleId: __moduleName, 
     selector: 'menu-item', 
     directives: [forwardRef(() => OptionsMenuComponent)], 
     templateUrl: 'menu-item.component.html', 
     styleUrls: ['menu-item.component.css'], 
    }) 
    export class MenuItemComponent { 
     @Input() menuItem: MenuItem; 

     constructor() { } 

    } 

注:我刪除了幾乎所有的邏輯和設計簡化,因爲它是不相關的

正如你可以看到OptionsMenuComponent知道MenuItemComponent和周圍的其他方式。
另外,您可能已經注意到,在MenuItemComponent中,我在指令中使用了forwardRef。如果沒有,當我加載頁面我收到以下錯誤:

Error: Uncaught (in promise): Unexpected directive value 'undefined' on the View of component 'MenuItemComponent'

目前,它的偉大工程,但TSLint是不滿,並輸出下面的這是寫(與forwardRef)的方式:

[gulp-tslint] error (no-forward-ref) menu-item.component.ts[9, 18]: Avoid using forwardRef in class "MenuItemComponent"

我環顧網絡尋找替代解決方案並空手而去。所有我能找到的是兩個建議:

  • 我與forwardRef
  • 「你有一個循環引用,你正在做的事情錯了,所以去耦」(不是原話)解決方案

第一個建議的作品,但我的問題是,如果有可能避免這種情況,因爲它聽起來不是很好的做法(並且到處都有人說要避免它)

第二個建議對於大多數情況是正確和容易實現的,但是如何我是否在遞歸st中做到這一點?結構(使用angular2組件)?提前

感謝,

PS - 在這之前,我把所有的功能在一個組件,我沒有與單一成分引用本身的任何問題(無需forwardRef),所以請不要建議這樣做,因爲它是不是這裏的情況(試圖保持部件小而簡單)

TL; DR:
兩個組件引用對方(遞歸結構是必需的)。 沒有使用forwardRef我得到錯誤,是否有一個不涉及使用forwardRef的替代解決方案?

+0

這是一個老問題,所以我認爲這是通過ngModules解決? –

+0

@SanderElias ngModules究竟解決了什麼問題? –

+0

像這樣的問題。它使您能夠將代碼捆綁到一個模塊中,因此它不需要您在每個組件中包含所有內容。 –

回答

0

這裏是我寫的遞歸導航的一個例子,簡化爲一個有序列表。總之,你定義一個模板,遞歸,然後遍歷根的孩子(網頁集合)context:{ $implicit: root.children },並在每一個孩子,通過改變上下文context:{ $implicit: page.children }遍歷根的孩子的孩子。

<ng-template #nav let-pages> 
    <ol> 
    <ng-container *ngFor="let page of pages"> 
     <ng-container *ngIf="page.public && page.visible"> 
     <li> 
      <a routerLink="/{{page.urlname}}">{{page.name}}</a> 
      <ng-container *ngTemplateOutlet="nav; context:{ $implicit: page.children }"></ng-container> 
     </li> 
     </ng-container> 
    </ng-container> 
    </ol> 
</ng-template> 
<ng-container *ngTemplateOutlet="nav; context:{ $implicit: root.children }"></ng-container>