如何在视图中仅循环一次对象(单个 *ngFor)?
How to loop through an object only once in the view (single *ngFor)?
我有这个对象,每个 属性 都有一个数组作为它的值。我只想循环一次这个对象而不是使用 2 *ngFor 指令,因为它会导致我的应用程序运行缓慢。我也愿意从此对象创建一个数组,但我仍然想为每个部分添加一个部分 ID,如下例所示。谁能指出我正确的方向?非常感谢!这是我的代码。
<div *ngFor="let group of dataObject | keyvalue">
{{group.key}}
<div *ngFor="let item of group.value; let i=index;">
{{item.name}}
</div>
</div>
注意:我的最终目标是将每个人包装到他们所属的部分,并为每个部分添加一个 id。
示例:
<div id = "parentId">
<div id = "section-a">
list of all users that belong in section a
</div>
<div id = "section-b">
list of all users that belong in section b
</div>
<div id = "section-c">
list of all users that belong in section c
</div>
<div>
......
......
</div>
无法使用 *ngFor
执行此操作。您可以在组件中准备一个平面版本的数据,并提供一个深度为 1 的数组以仅循环一次。
示例 AppComponent:
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html"
})
export class AppComponent {
dataObject = {
A: [
{ id: 1, name: "Mike", lastname: "asmith" },
{ id: 2, name: "Mary", lastname: "alters" },
{ id: 3, name: "Boris", lastname: "al" }
],
B: [
{ id: 1, name: "Mike", lastname: "bmith" },
{ id: 2, name: "Mary", lastname: "balters" },
{ id: 3, name: "Boris", lastname: "bl" }
],
C: [
{ id: 1, name: "Mike", lastname: "cmith" },
{ id: 2, name: "Mary", lastname: "calters" },
{ id: 3, name: "Boris", lastname: "dl" }
],
D: [
{ id: 1, name: "Mike", lastname: "dmith" },
{ id: 2, name: "Mary", lastname: "dalters" },
{ id: 3, name: "Boris", lastname: "dl" }
],
E: [
{ id: 1, name: "Mike", lastname: "emith" },
{ id: 2, name: "Mary", lastname: "ealters" },
{ id: 3, name: "Boris", lastname: "el" }
]
};
flatDataObject = [];
constructor() {
// Loop through dataObject
Object.keys(this.dataObject).forEach(k => {
// Assign key as a `key` attribute to first object in array.
this.dataObject[k][0].key = k;
// Push the arrays into one
this.flatDataObject.push(...this.dataObject[k]);
});
}
}
示例HTML:
<div *ngFor="let group of flatDataObject">
<!-- Check if the object has `key` attribute -->
<div *ngIf="group.key">
<!-- If it has `key` attribute: -->
{{group.key}}
</div>
<div>
{{group.lastname}}
</div>
</div>
这是演示:https://stackblitz.com/edit/angular-6-template-sk8tkm?file=src/app/app.component.html
这是我能想到的最好的解决方案。它仍然总共有两个循环,但至少其中一个没有使用 *ngFor
.
你有一个 Dictionary
of Array
s(作为数据结构),所以你有以下必要迭代的时间复杂度:
O(n)
: n
代表字典[=45]的长度 =]
O(m)
: m
代表长度的值(类型Array
)
您执行迭代的总复杂度为 O(mn)
或 O(m*n)
任何地方。例如下面的代码具有相同的时间复杂度:
Object.entries(this.dataObject).reduce((result, entry) => {
const [key, value] = entry;
value.forEach((v, i) => (result[`${key}_${i}`] = v.name));
return result;
},{});
如果你有限制,我认为你可以减少 借助语言方法和像下面这样的方便技巧的时间复杂度:
Object.values(this.dataObject).map(m => m).flat().map(m => m.name);
然后,拆分每 3 个项目:
<div *ngFor="let item of simplified2; let i = index" [id]="findId(i)">
{{findId(i)}} {{item}}
</div>
findId(index: number) {
return Math.floor(index / 3); //if you are sure about the length of values
}
我在 stackblitz. You can study more about Data Structures in JavaScript: Arrays, HashMaps, and Lists
中提供了上述所有内容
您可以生成一个新的 属性 reduced 并使用这个新的 属性
在你的组件中
dataObject = {
A: [
{id: 1, name: 'Mike', lastname: 'asmith'},
{id: 2, name: 'Mary', lastname: 'alters'},
{id: 3, name: 'Boris', lastname: 'al'}
],
B: [
{id: 1, name: 'Lauren', lastname: 'bmith'},
{id: 2, name: 'Travis', lastname: 'balters'},
{id: 3, name: 'Barn', lastname: 'bl'}
],
...
}
dataObjectDisp = Object.entries(this.dataObject).reduce((prev, [key, value]) =>{
return [...prev, ...value.map((user, index) => ({
...user, parent: key, index }))]
}, [])
以上代码会将结构缩减为
[
{
"id": 1,
"name": "Mike",
"lastname": "asmith",
"parent": "A",
"index": 0
},
{
"id": 2,
"name": "Mary",
"lastname": "alters",
"parent": "A",
"index": 1
},
...
]
现在我们有办法确定新部分何时开始。它的索引将为零
要显示 html 您可以执行如下操作
<h1>New</h1>
<div *ngFor="let item of dataObjectDisp; let i = index" [attr.data-article]='"section" + item.parent'>
<ng-container *ngIf="item.index === 0">
{{ item.parent }}
</ng-container>
<div>
{{item.lastname}}
</div>
</div>
注意属性 [attr.data-article]='"section" + item.parent'
。这可以用来识别不同的部分
我有这个对象,每个 属性 都有一个数组作为它的值。我只想循环一次这个对象而不是使用 2 *ngFor 指令,因为它会导致我的应用程序运行缓慢。我也愿意从此对象创建一个数组,但我仍然想为每个部分添加一个部分 ID,如下例所示。谁能指出我正确的方向?非常感谢!这是我的代码。
<div *ngFor="let group of dataObject | keyvalue">
{{group.key}}
<div *ngFor="let item of group.value; let i=index;">
{{item.name}}
</div>
</div>
注意:我的最终目标是将每个人包装到他们所属的部分,并为每个部分添加一个 id。 示例:
<div id = "parentId">
<div id = "section-a">
list of all users that belong in section a
</div>
<div id = "section-b">
list of all users that belong in section b
</div>
<div id = "section-c">
list of all users that belong in section c
</div>
<div>
......
......
</div>
无法使用 *ngFor
执行此操作。您可以在组件中准备一个平面版本的数据,并提供一个深度为 1 的数组以仅循环一次。
示例 AppComponent:
import { Component } from "@angular/core";
@Component({
selector: "app-root",
templateUrl: "./app.component.html"
})
export class AppComponent {
dataObject = {
A: [
{ id: 1, name: "Mike", lastname: "asmith" },
{ id: 2, name: "Mary", lastname: "alters" },
{ id: 3, name: "Boris", lastname: "al" }
],
B: [
{ id: 1, name: "Mike", lastname: "bmith" },
{ id: 2, name: "Mary", lastname: "balters" },
{ id: 3, name: "Boris", lastname: "bl" }
],
C: [
{ id: 1, name: "Mike", lastname: "cmith" },
{ id: 2, name: "Mary", lastname: "calters" },
{ id: 3, name: "Boris", lastname: "dl" }
],
D: [
{ id: 1, name: "Mike", lastname: "dmith" },
{ id: 2, name: "Mary", lastname: "dalters" },
{ id: 3, name: "Boris", lastname: "dl" }
],
E: [
{ id: 1, name: "Mike", lastname: "emith" },
{ id: 2, name: "Mary", lastname: "ealters" },
{ id: 3, name: "Boris", lastname: "el" }
]
};
flatDataObject = [];
constructor() {
// Loop through dataObject
Object.keys(this.dataObject).forEach(k => {
// Assign key as a `key` attribute to first object in array.
this.dataObject[k][0].key = k;
// Push the arrays into one
this.flatDataObject.push(...this.dataObject[k]);
});
}
}
示例HTML:
<div *ngFor="let group of flatDataObject">
<!-- Check if the object has `key` attribute -->
<div *ngIf="group.key">
<!-- If it has `key` attribute: -->
{{group.key}}
</div>
<div>
{{group.lastname}}
</div>
</div>
这是演示:https://stackblitz.com/edit/angular-6-template-sk8tkm?file=src/app/app.component.html
这是我能想到的最好的解决方案。它仍然总共有两个循环,但至少其中一个没有使用 *ngFor
.
你有一个 Dictionary
of Array
s(作为数据结构),所以你有以下必要迭代的时间复杂度:
O(n)
:n
代表字典[=45]的长度 =]O(m)
:m
代表长度的值(类型Array
)
您执行迭代的总复杂度为 O(mn)
或 O(m*n)
任何地方。例如下面的代码具有相同的时间复杂度:
Object.entries(this.dataObject).reduce((result, entry) => {
const [key, value] = entry;
value.forEach((v, i) => (result[`${key}_${i}`] = v.name));
return result;
},{});
如果你有限制,我认为你可以减少 借助语言方法和像下面这样的方便技巧的时间复杂度:
Object.values(this.dataObject).map(m => m).flat().map(m => m.name);
然后,拆分每 3 个项目:
<div *ngFor="let item of simplified2; let i = index" [id]="findId(i)">
{{findId(i)}} {{item}}
</div>
findId(index: number) {
return Math.floor(index / 3); //if you are sure about the length of values
}
我在 stackblitz. You can study more about Data Structures in JavaScript: Arrays, HashMaps, and Lists
中提供了上述所有内容您可以生成一个新的 属性 reduced 并使用这个新的 属性
在你的组件中
dataObject = {
A: [
{id: 1, name: 'Mike', lastname: 'asmith'},
{id: 2, name: 'Mary', lastname: 'alters'},
{id: 3, name: 'Boris', lastname: 'al'}
],
B: [
{id: 1, name: 'Lauren', lastname: 'bmith'},
{id: 2, name: 'Travis', lastname: 'balters'},
{id: 3, name: 'Barn', lastname: 'bl'}
],
...
}
dataObjectDisp = Object.entries(this.dataObject).reduce((prev, [key, value]) =>{
return [...prev, ...value.map((user, index) => ({
...user, parent: key, index }))]
}, [])
以上代码会将结构缩减为
[
{
"id": 1,
"name": "Mike",
"lastname": "asmith",
"parent": "A",
"index": 0
},
{
"id": 2,
"name": "Mary",
"lastname": "alters",
"parent": "A",
"index": 1
},
...
]
现在我们有办法确定新部分何时开始。它的索引将为零
要显示 html 您可以执行如下操作
<h1>New</h1>
<div *ngFor="let item of dataObjectDisp; let i = index" [attr.data-article]='"section" + item.parent'>
<ng-container *ngIf="item.index === 0">
{{ item.parent }}
</ng-container>
<div>
{{item.lastname}}
</div>
</div>
注意属性 [attr.data-article]='"section" + item.parent'
。这可以用来识别不同的部分