8

次の 2 つのコンポーネントで構成される再帰構造があります。

  • OptionsMenuComponent (Aメニュー)
  • 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 を使用していることに気付いたかもしれません。それがないと、ページをロードすると次のエラーが発生します。

エラー: キャッチされていません (約束されています): コンポーネント 'MenuItemComponent' のビューに予期しないディレクティブ値 'undefined' があります

現在、(forwardRefを使用して)書かれた方法ではうまく機能しますが、TSLintはそれに不満を持っており、次のように出力します:

[gulp-tslint] エラー (no-forward-ref) menu-item.component.ts[9, 18]: クラス "MenuItemComponent" で forwardRef を使用しない

私は別の解決策を求めてウェブを見回しましたが、手ぶらで出てきました。私が見つけたのは2つの提案だけです:

  • forwardRef を使用した私のソリューション
  • 「あなたは循環参照を持っています。あなたは何か間違ったことをしているので、それらを切り離してください」(正確な言葉ではありません)

最初の提案はうまくいきますが、私の質問は、これを避けることができるかどうかです。

2 番目の提案は正しく、ほとんどの場合に簡単に実装できますが、(angular2 コンポーネントを使用して) 再帰構造でそれを行うにはどうすればよいですか?

よろしくお願いします。

ps - これより前は、1 つのコンポーネントにすべての機能があり、その単一のコンポーネントがそれ自体を参照することに問題はありませんでした (forwardRef は必要ありません)。コンポーネントは小さくてシンプルです)

TL;DR:
2 つのコンポーネントが相互に参照しています (再帰構造が必要でした)。forwardRef を使用しないとエラーが発生します。forwardRef を使用しない代替ソリューションはありますか?

4

1 に答える 1

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>
于 2018-01-22T23:17:27.243 に答える