我知道有很多类似的问题,几乎所有问题都以 DynamicComponentLoader 的答案结尾,但我仍然认为下面描述的用例是如此简单和常见(IMO),以至于 Angular 2 的解决方案应该是直截了当的。
示例用例
我有一组新闻项目,其属性 type
描述了它是什么类型的项目。
var items = [
{ id: 1, type: 'text', data: {} },
{ id: 2, type: 'text', data: {} },
{ id: 3, type: 'text-two-columns', data: {} },
{ id: 4, type: 'image-text', data: {} },
{ id: 5, type: 'image', data: {} },
{ id: 6, type: 'twitter', data: {} },
{ id: 7, type: 'text', data: {} }
]
每种不同的类型都有不同的view
和背后完全不同的逻辑。换句话说 - 每个 type
都有自己的 angular2 Component
。
我尝试实现的抽象代码是:
<div *ngFor="let item of items">
<item-{{item.type}} [data]="item.data"></item-{{item.type}}>
</div>
当然不行。
可能的解决方案 #1
<div *ngFor="let item of items">
<item-text *ngIf="item.type === 'text'" [data]="item.data"></item-text>
<item-image *ngIf="item.type === 'image'" [data]="item.data"></item-image>
...
</div>
我不喜欢这个解决方案,不仅因为它看起来很丑,而且每次我添加新类型时都必须包含这一行,而且我想知道这个解决方案从性能 Angular 来看是否不错?我的意思是如果我有 10,000 种不同的类型并且只显示 3 个项目。因此 angular2 必须从 DOM 中删除 9,999 个标签,并且为 3 个项目中的每一个只保留一个标签(3 * 9999 次删除操作)。
可能的解决方案#2
<div *ngFor="let item of items">
<dynamic-component-loader [item]="item"></dynamic-component-loader>
</div>
目前我不记得 DynamicComponentLoader
是如何工作的(很久以前我在 angular2 alpha 中的类似问题中尝试过)。但我记得代码对我来说看起来像 hack
.. 对于这样的常见任务?..
Angular 1.x 思维
我不知道我做错了什么,也许问题是我仍然在 Angular 1
中思考?使用它时,我会使用 ngInclude
或带有模板函数的自定义指令。
兄弟们,你们有没有其他的解决方法呢?不要坚持我的两个潜在解决方案,也许我需要跳出框框思考并在我的应用程序的不同部分完全解决这个问题。我很困惑。谢谢:)
编辑:另一个现实世界的例子
假设您的任务是使用 Angular 2 编写 Facebook。我认为您在尝试显示新闻提要时会遇到同样的问题。每个新闻提要项都有其类型(文本
、事件
、广告
、..)
最佳答案
这是我的解决方案:
import { Component, OnInit, ViewContainerRef, TemplateRef, ComponentFactoryResolver, Input } from '@angular/core';
@Component({
selector: 'item',
template: '',
styleUrls: ['./item.component.scss']
})
export class ItemComponent implements OnInit {
@Input() type: string;
@Input() data: any;
constructor(
private viewContainerRef: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver,
private componentLookupService: YourComponentLookUpService
) { }
ngOnInit() {
const component = this.componentLookupService.findByType(type);
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
// Look at the https://angular.io/docs/ts/latest/api/core/index/ViewContainerRef-class.html#!#createComponent-anchor for more information about how to use DI... in the createComponent function.
const componentRef =this.viewContainerRef.createComponent(componentFactory);
// Or you can then access the newly created component here: this.componentRef.instance
}
}
在你的 NgFor 循环中:
<div *ngFor="let item of items">
<item [type]="item.type" [data]="item.data"></item>
</div>
关于javascript - Angular 2 ngFor 中不同组件的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40578400/