首先,我想提一下,我不是一个 Angular 开发人员,几乎我所有的技能都属于后端工作,但我正在努力解决这个概念,我什至不知道它是否是可能的。谷歌搜索没有多大帮助,因为我什至不知道如何正确地表达这个问题,所以我希望描述一下情况,我想做什么,我希望它如何工作,并希望得到一些关于我正在尝试做的事情的建议实际上在 Angular 世界中被称为“是否可能”,以及“假设可能”,它会是什么样子的示例。
我们有一个具有 .NET Core Web API 后端的 SPA。有一个 API 端点 /api/feedItems
,它返回“提要项目”列表,大致相当于事件日志。
提要项目的基本形状类似于:
export enum FeedItemType {
undefined = "undefined",
foo = "foo",
bar = "bar"
}
export class FeedItemModel {
id: number;
createdUtcTimestamp: Date;
feedType: FeedItemType;
feedData: {} // object? any?
}
这里的想法是,所有提要项目都将具有某些元数据,包括 ID、时间戳、提要类型标识符和有效负载。实际有效负载内容将根据 FeedItemType
的不同而有所不同。
从 API 调用返回的示例提要项目列表可能类似于以下内容:
[
{
"id":12345,
"createdUtcTimestamp":"2018-12-05T13:30:00Z",
"feedType":"foo",
"feedData":{
"name":"this is a foo type feed",
"description":"This foo feed is describing an event of type 'foo'"
}
},
{
"id":67890,
"createdUtcTimestamp":"2018-12-06T15:45:00Z",
"feedType":"bar",
"feedData":{
"value1":11111,
"value2":22222,
"value3":33333
}
}
]
我们实际上有很多不同的 Feed 项类型,每种类型都应该有自己的自定义呈现,以便以最有用的方式可视化数据。
我想要做的是有一个 Angular 组件,负责从 API 获取提要项目列表并循环访问提要项目。对于每个 feed 项(大概在 *ngFor 指令中),它应该呈现公共(public)属性,然后根据 feedType
呈现不同的“子”组件。
在本例中,假设我的容器组件如下所示:
<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
<div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>
<!-- equivalent of "if feedItem.feedType == 'foo'",
possibly ngIf or ngSwitch, but I'd prefer to not
have to explicitly check for each type -->
<feed-item-foo (I have no idea how to pass the feedData to this component) />
<!-- equivalent of "if feedItem.feedType == 'bar'" -->
<feed-item-bar (again, this is a mystery what should go here) />
<!-- equivalent of "if can't match on feedType" -->
<feed-item-generic (something) />
</div>
</div>
这里的想法是,我可以根据需要在该文件之外创建组件,而无需对容器模板进行许多更改(最好不进行任何更改)。如果我能够以编程方式识别 feedType,为其查找已注册的组件选择器,并自动将 feedData 传递给它,那将是理想的选择,但如果我必须手动引用这个容器中的每个组件,也可以。我只是不想将所有渲染逻辑都放在这个容器中,因为这很快就会变得笨拙且难以管理。
提要项组件将根据提要类型拥有自己的格式、不同的样式以及可能不同的逻辑操作。我不需要一个巨大的 feedItem 容器组件。
那么,这可能吗?如果是这样,我该怎么办?
最佳答案
如果我能正确理解的话,也许下面的想法可以帮助你。 我以你的例子为例并稍加修改。
<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
<div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>
<!-- equivalent of "if feedItem.feedType == 'foo'",
possibly ngIf or ngSwitch, but I'd prefer to not
have to explicitly check for each type -->
<!-- i do not know of any alternative, but to make it a bit more readable
you can use <ng-container>
<ng-container *ngIf="feedItem.feedType === 'foo'">
<!-- you can create your own component and add an @Input() data, so your component will know what it is dealing with (see example below)
<feed-item-foo [data]="feedItem"/>
</ng-container>
<!-- equivalent of "if feedItem.feedType == 'bar'" -->
<ng-container *ngIf="feedItem.feedType === 'bar'">
<!-- you can create your own component and add an @Input() data, so
your component will know what it is dealing with (see example below)
<feed-item-bar [data]="feedItem"/>
</ng-container>
<!-- equivalent of "if can't match on feedType" -->
<!-- that is a bit of a pain in the ... -->
<ng-container *ngIf='!foo && !bar && !xyz'>
<feed-item-generic (something) />
</ng-container>
</div>
您的组件可以而且应该全部包含类似“基”类的内容
export class FeedItemBase implements OnInit {
@Input() data = <YourType>null; // that is a little hack to get the type
// correct (was some bug in a angular 4 version as far as i remember)
constructor() {
}
ngOnInit() {
// if needed .. if not, delete it :)
}
}
然后所有其他类都可以扩展基类(因为数据将始终相同......
export class FeedItemFoo extends FeedItemBase implements OnInit {
constructor() {
}
ngOnInit() {
// here you can access data already
}
}
如果你只有两种类型(我对此表示怀疑),你也可以这样做:
<div class="feed-item-container" *ngFor="let feedItem of feedItemList; let i = index;">
<div class="feed-item">
<div class="timestamp-display">{{feedItem.createdUtcTimestamp}}</div>
<!-- equivalent of "if feedItem.feedType == 'foo'",
possibly ngIf or ngSwitch, but I'd prefer to not
have to explicitly check for each type -->
<!-- i do not know of any alternative, but to make it a bit more readable
you can use <ng-template>
<ng-container *ngIf="feedItem.feedType === 'foo'; then fooId;else barId">
</ng-container>
<ng-template #fooId>
<!-- you can create your own component and add an @Input() data, so your component will know what it is dealing with (see example below)
<feed-item-bar [data]="feedItem"/>
</ng-template>
<!-- equivalent of "if feedItem.feedType == 'bar'" -->
<ng-template #barId>
<!-- you can create your own component and add an @Input() data, so
your component will know what it is dealing with (see example below)
<feed-item-foo [data]="feedItem"/>
</ng-container>
<!-- equivalent of "if can't match on feedType" -->
<!-- that is a bit of a pain in the ... -->
<ng-container *ngIf='!foo && !bar && !xyz'>
<feed-item-generic (something) />
</ng-container>
</div>
希望有帮助:)
关于来自共同来源的 Angular 条件分量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53693053/