尝试了我能猜到的每种语法都无法使其正常工作!
<!--- THIS WORKS FINE --->
<ion-card *ngFor="#post of posts">
{{post|json}}
</ion-card>
<!--- BLANK PAGE --->
<ion-card *ngFor="#post of posts track by post.id">
{{post|json}}
</ion-card>
<!--- Exception : Cannot read property 'id' of undefined --->
<ion-card *ngFor="#post of posts;trackBy:post.id">
{{post|json}}
</ion-card>
<!--- Exception : Cannot read property 'undefined' of undefined --->
<ion-card *ngFor="#post of posts;trackBy:posts[index].id">
{{post|json}}
</ion-card>
<!--- Blank page no exception raised ! --->
<ion-card *ngFor="#post of posts;#index index;trackBy:posts[index].id">
{{post|json}}
</ion-card>
对我有用的唯一方法是
在控制器类中创建方法
标识(索引,交张贴){ 返回post.id }
和
<ion-card *ngFor="#post of posts;trackBy:identify">
</ion-card>
这是唯一的方法吗?我不能只为trackBy指定内联属性名称吗?
答案 0 :(得分:79)
正如在@Eric评论中所指出的,经过大量的阅读和游戏,这里是如何在angular2中使用trackBy
// starting v2. 1 this will throw error, you can only use functions in trackBy from now on
<ion-card *ngFor="let post of posts;trackBy:post?.id">
</ion-card> // **DEPRECATED**
---or---
<ion-card *ngFor="let post of posts;trackBy:trackByFn">
</ion-card>
的for循环分开。用法1:按对象属性进行跟踪
// starting v2. 1 this will throw error, you can only use functions in trackBy from now on
*ngFor="#post of posts;trackBy:post?.id"
这里你问angular2到
所以
ng-repeat="post in posts track by post.id"
与angular&#39; s
相同@Page({
template: `
<ul>
<li *ngFor="#post of posts;trackBy:identify">
{{post.data}}
</li>
</ul>
`
})
export class HomeworkAddStudentsPage {
posts:Array<{id:number,data:string}>;
constructor() {
this.posts = [ {id:1,data:'post with id 1'},
{id:2,data:'post with id 2'} ];
}
identify(index,item){
//do what ever logic you need to come up with the unique identifier of your item in loop, I will just return the object id.
return post.id
}
}
用法2:使用您自己的功能跟踪
<li ng-repeat="post in posts track by identify($index,post)"></li>
app.controller(function($scope){
$scope.identify = function(index, item) {return item.id};
});
trackBy可以采用回调的名称,它将为我们提供2个参数来调用它:循环的索引和当前项。
为了实现与Angular 1的相同,我曾经这样做:
nrMessages
答案 1 :(得分:9)
正如您已经认识到的那样,使用函数是在Angular 2中使用trackBy
的唯一方法
<ion-card *ngFor="#post of posts;trackBy:identify"></ion-card>
官方文件指出QueryBuilders
有关<ion-card *ngFor="let post of posts;trackBy:post?.id"></ion-card>
的所有其他信息都是错误的。从Angular 2.4.1开始,这也会在应用程序中引发错误。
答案 2 :(得分:2)
trackBy背后的概念:
ngFor
通过跟踪对象标识自动优化修改/创建/删除对象的显示。
因此,如果您在列表中创建所有新对象,然后使用ngFor
,它将呈现整个列表。
让我们考虑一个场景,尽管进行了所有ngFor
次优化,渲染仍然需要时间。在这种情况下,我们使用trackBy
。因此,我们可以提供另一个参数来跟踪对象,而不是作为默认跟踪条件的对象标识。
一个正在运行的例子:
<!DOCTYPE html>
<html>
<head>
<title>Angular 2.1.2 + TypeScript Starter Kit</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://unpkg.com/zone.js@0.6.21/dist/zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.9/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.41/dist/system.js"></script>
<script src="https://unpkg.com/typescript@2.1.4/lib/typescript.js"></script>
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
答案 3 :(得分:2)
除了其他人的答案外,只想添加一些示例(Angular 2+),以便清楚地使用trackBy。
摘自文档:
为避免此昂贵的操作,您可以自定义默认值 跟踪算法。通过向NgForOf提供trackBy选项。 trackBy采用的函数具有两个参数:index和item。如果 给出trackBy,角度轨迹会根据 功能。
在此处了解更多信息:https://angular.io/api/common/NgForOf
一个例子会更好地解释它。
app.component.ts
array = [
{ "id": 1, "name": "bill" },
{ "id": 2, "name": "bob" },
{ "id": 3, "name": "billy" }
]
foo() {
this.array = [
{ "id": 1, "name": "foo" },
{ "id": 2, "name": "bob" },
{ "id": 3, "name": "billy" }
]
}
identify(index, item) {
return item.id;
}
让我们使用array
将*ngFor
显示为3格。
app.component.html
*ngFor
没有trackBy 的示例:
<div *ngFor="let e of array;">
{{e.id}} - {{e.name}}
</div>
<button (click)="foo()">foo</button>
如果我们点击foo
按钮会发生什么?
→3格将被刷新。 尝试一下,打开控制台进行验证。
*ngFor
带有trackBy 的示例:
<div *ngFor="let e of array; trackBy: identify">
{{e.id}} - {{e.name}}
</div>
<button (click)="foo()">foo</button>
如果我们点击foo
按钮会发生什么?
→仅刷新第一个div。 尝试一下,打开控制台进行验证。
如果我们更新第一个对象而不是整个对象怎么办?
foo() {
this.array[0].name = "foo";
}
→此处无需使用trackBy
。
在使用 Subscription (通常类似于我用array
模式化的内容)时,它特别有用。因此,它看起来像:
array = [];
subscription: Subscription;
ngOnInit(): void {
this.subscription = this.fooService.getArray().subscribe(data => {
this.array = data;
});
}
identify(index, item) {
return item.id;
}
答案 4 :(得分:-5)
这个简单的解决方案适用于我的场景
<ion-card *ngFor="let post of posts;let i = index">
{{i+1}}
</ion-card>
编辑:根据Jeremy Thille的建议,您应该使用let
代替#
,因为最新版本的Angular2中不推荐使用#
。