以递归方式使用组件来创建树

时间:2016-06-10 10:58:02

标签: angular components

您知道是否可以自行使用组件?如果是的话,在哪里阅读它?

我有下一个情况: 拥有mainItems列表,每个Main Item都有subItem(看起来像mainItem),每个subItem都可以拥有它自己的subItem等。 所以最好使用嵌套,但是如何?

3 个答案:

答案 0 :(得分:35)

<强>更新

forwardRef()不再需要了,因为directives已移至NgModule.declarations,因此递归组件不再需要在directives上注册。

Angular 4.x.x Plunker example

<强>原始

支持。您只需将组件添加到directives: []装饰器中的@Component()即可。因为装饰器出现在类之前,并且在声明它们之前无法引用类forwardRef()

import {Component, forwardRef, Input} from '@angular/core'

@Component({
  selector: 'tree-node',
  template: `
  <div>{{node.name}}</div>
  <ul>
    <li *ngFor="let node of node.children">
      <tree-node  [node]="node"></tree-node>
    </li>
  </ul>
`
})
export class TreeNode {
  @Input() node;
}
    
@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <tree-node [node]="node"></tree-node>
    </div>
  `,
  directives: [TreeNode]
})
export class App {
  constructor() {
    this.name = 'Angular2 (Release Candidate!)'
  }

  node = {name: 'root', children: [
    {name: 'a', children: []},
    {name: 'b', children: []},
    {name: 'c', children: [
      {name: 'd', children: []},
      {name: 'e', children: []},
      {name: 'f', children: []},
     ]},
  ]};  
}

Angular 2.0.0-beta.x Plunker example

另见Inject parent component of the same type as child component

答案 1 :(得分:5)

Angular 4 递归组件示例:https://plnkr.co/edit/IrW82ye4NKK8cYEPxsFc?p=preview

摘录链接示例:

//our root app component
import {Component, NgModule, VERSION, Input} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Component({
  selector: 'tree-node',
  template: `
  <div>{{node.name}}</div>
  <ul>
    <li *ngFor="let node of node.children">
      <tree-node  [node]="node"></tree-node>
    </li>
  </ul>
`
})
export class TreeNode {
  @Input() node;
}

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <tree-node [node]="node"></tree-node>
    </div>
  `
})
export class App {
  constructor() {
    this.name = 'Angular2 (Release Candidate!)'
  }

  node = {name: 'root', children: [
    {name: 'a', children: []},
    {name: 'b', children: []},
    {name: 'c', children: [
      {name: 'd', children: []},
      {name: 'e', children: []},
      {name: 'f', children: []},
     ]},
  ]};  
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, TreeNode ],
  bootstrap: [ App ]
})
export class AppModule {}

此答案是社区维基,因为示例链接是从GünterZöchbauer的答案中复制的。我在问题正文中包含了代码以避免链接腐烂。

答案 2 :(得分:0)

使用ng-template是解决递归DOM问题的最佳解决方案。

@Component({
  selector: 'tree-node',
   template: `
     <ng-container *ngTemplateOutlet="tree;context:{node:node}">
     </ng-container>

     <ng-template #tree let-node="node">
       <div>{{node.name}}</div>
       <ul *ngIf="node.children && node.children.length > 0">
         <ng-container *ngFor="let child of node.children">
           <li>
             <ng-container *ngTemplateOutlet="tree;context:{node:child}">
             </ng-container>
           </li>
         </ng-container>
       </ul>
     </ng-template>
   `
})
export class TreeNode {
    @Input() node;
}

无需将组件添加到其directives: []中的@Component()中。

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <tree-node [node]="node"></tree-node>
    </div>
  `
})
export class App {

  node = {
    name: 'root', children: [
      { name: 'a', children: [] },
      {
        name: 'b', children: [
          { name: 'b-1', children: [] },
          {
            name: 'b-2', children: [
              { name: 'b-2-1', children: [] },
              { name: 'b-2-2', children: [] },
              { name: 'b-2-3', children: [] }
            ]
          }
        ]
      },
      {
        name: 'c', children: [
          { name: 'c-1', children: [] },
          { name: 'c-2', children: [] }
        ]
      },
    ]
  };

}

输出:

    • a
    • b
      • b-1
      • b-2
        • b-2-1
        • b-2-2
        • b-2-3
    • c
      • c-1
      • c-2

HTML:

<tree-node>
    <div>root</div>
    <ul>
        <li>
            <div>a</div>
        </li>
        <li>
            <div>b</div>
            <ul>
                <li>
                    <div>b-1</div>
                </li>
                <li>
                    <div>b-2</div>
                    <ul>
                        <li>
                            <div>b-2-1</div>
                        </li>
                        <li>
                            <div>b-2-2</div>
                        </li>
                        <li>
                            <div>b-2-3</div>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
        <li>
            <div>c</div>
            <ul>
                <li>
                    <div>c-1</div>
                </li>
                <li>
                    <div>c-2</div>
                </li>
            </ul>
        </li>
    </ul>
</tree-node>