递归地使用组件本身来创建树
Use component in itself recursively to create a tree
你知道组件本身可以使用吗?如果是,在哪里可以阅读?
我有下一个情况:
有 mainItems 列表,每个 Main Item 都有 subItem(看起来和 mainItem 一样),每个 subItem 可以有它自己的 subItem 等等。
所以最好使用嵌套,但是如何?
更新
forwardRef()
不再需要,因为 directives
已移至 NgModule.declarations
,因此递归组件不再需要将其自身注册为 directives
。
原创
支持。您只需要在其 @Component()
装饰器中将组件添加到 directives: []
。因为装饰器出现在 class 之前,并且 classes 在它们被声明之前不能被引用 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
Angular 4递归分量的例子:https://plnkr.co/edit/IrW82ye4NKK8cYEPxsFc?p=preview
摘自 linked 示例:
//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 {}
这个答案是社区 wiki 因为示例 link 是从 Günter Zöchbauer 的答案中复制的。我将代码包含在问题正文中以避免 link rot.
使用 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;
}
无需在其 @Component()
中将组件添加到 directives: []
。
@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: [] }
]
},
]
};
}
输出:
- 根
- 一个
- 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>
你知道组件本身可以使用吗?如果是,在哪里可以阅读?
我有下一个情况: 有 mainItems 列表,每个 Main Item 都有 subItem(看起来和 mainItem 一样),每个 subItem 可以有它自己的 subItem 等等。 所以最好使用嵌套,但是如何?
更新
forwardRef()
不再需要,因为 directives
已移至 NgModule.declarations
,因此递归组件不再需要将其自身注册为 directives
。
原创
支持。您只需要在其 @Component()
装饰器中将组件添加到 directives: []
。因为装饰器出现在 class 之前,并且 classes 在它们被声明之前不能被引用 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
Angular 4递归分量的例子:https://plnkr.co/edit/IrW82ye4NKK8cYEPxsFc?p=preview
摘自 linked 示例:
//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 {}
这个答案是社区 wiki 因为示例 link 是从 Günter Zöchbauer 的答案中复制的。我将代码包含在问题正文中以避免 link rot.
使用 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;
}
无需在其 @Component()
中将组件添加到 directives: []
。
@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: [] }
]
},
]
};
}
输出:
- 根
- 一个
- 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>