如何在ngFor angular 2中使用track

Zal*_*oza 46 angularjs-track-by ngfor angular

尝试了我能猜出的每一种语法都无法使其有效!

<!--- 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>
Run Code Online (Sandbox Code Playgroud)

对我有用的唯一方法是

  1. 在控制器类中创建方法

    识别(索引,帖子:帖子){return post.id}

<ion-card *ngFor="#post of posts;trackBy:identify">
</ion-card>
Run Code Online (Sandbox Code Playgroud)

这是唯一的方法吗?我不能只为trackBy指定内联属性吗?

Zal*_*oza 85

正如在@Eric评论中指出的,经过大量的阅读和游戏,这里是如何在angular2中使用trackBy

  1. 首先你需要知道它与angular1的语法不同,现在你需要将它与for循环分开;.

用法1:按对象属性进行跟踪

 // 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>
Run Code Online (Sandbox Code Playgroud)

在这里你问angular2到

  1. 创建一个局部变量帖子;
  2. 你告诉trackBy要等到这个局部变量准备就绪"你通过使用elvis operator'变量名后面的问号',然后使用它的id作为跟踪器.

所以

// starting v2. 1 this will throw error, you can only use functions in trackBy from now on

*ngFor="#post of posts;trackBy:post?.id"
Run Code Online (Sandbox Code Playgroud)

与棱镜1相同

ng-repeat="post in posts track by post.id"
Run Code Online (Sandbox Code Playgroud)

用法2:使用您自己的功能进行跟踪

@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 
     }

}
Run Code Online (Sandbox Code Playgroud)

trackBy可以采用回调的名称,它将为我们调用它提供2个参数:循环的索引和当前项.

为了实现与Angular 1相同,我曾经做过:

<li ng-repeat="post in posts track by identify($index,post)"></li>

app.controller(function($scope){
  $scope.identify = function(index, item) {return item.id};
});
Run Code Online (Sandbox Code Playgroud)

  • 我确认,trackBy仅适用于函数,它不会出现"post?.id"错误,但在这种情况下它会跟踪"null"(你可以检查html并查看),这意味着它不跟踪你根本没有看到错误@Zalaboza你能更新你的帖子,这样它对新用户没有误导性吗? (17认同)
  • 我不认为"trackBy:post?.id"有效.在我的例子中,子元素的状态丢失了.单独的trackBy函数可以工作(但绝对不方便).顺便说一句,猫王操作员本身表明出了问题.如果它有效,那么你不必在这里使用它(除非集合项可以为null). (4认同)
  • 对@Zalaboza,只允许功能,请更新你的帖子.在这里讨论:https://github.com/angular/angular/issues/13641#issuecomment-269082370 (3认同)
  • 除了@Olivier 评论。从 Angular 2.4.1 开始,使用 *ngFor="#post of posts;trackBy:post?.id" 会抛出错误,因为 trackBy 只接受函数 (2认同)

Vol*_*res 9

正如您已经认识到的那样,使用函数是trackBy在Angular 2中使用的唯一方法

<ion-card *ngFor="#post of posts;trackBy:identify"></ion-card>
Run Code Online (Sandbox Code Playgroud)

官方文档说明https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html

所有其他信息<ion-card *ngFor="let post of posts;trackBy:post?.id"></ion-card>都是错误的.从Angular 2.4.1开始,这也会在应用程序中引发错误.


Cur*_*rse 5

除了其他人的答案之外,只想添加一些示例(Angular 2+)以明确使用 trackBy。

从文档:

为了避免这种昂贵的操作,您可以自定义默认跟踪算法。通过向 NgForOf 提供 trackBy 选项。trackBy 接受一个有两个参数的函数:index 和 item。如果给定了 trackBy,Angular 会根据函数的返回值跟踪变化。

在此处阅读更多信息: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;
   }
Run Code Online (Sandbox Code Playgroud)

让我们array使用*ngFor.

应用程序组件.html

的实施例*ngFor ,而不trackBy

<div *ngFor="let e of array;">
   {{e.id}} - {{e.name}}
</div>
<button (click)="foo()">foo</button>
Run Code Online (Sandbox Code Playgroud)

如果我们点击foo按钮会发生什么?

? 3 个 div 将被刷新。自己尝试一下,打开控制台进行验证。

的实施例*ngFor 与trackBy

<div *ngFor="let e of array; trackBy: identify">
   {{e.id}} - {{e.name}}
</div>
<button (click)="foo()">foo</button>
Run Code Online (Sandbox Code Playgroud)

如果我们点击foo按钮会发生什么?

? 只有第一个 div 会被刷新。自己尝试一下,打开控制台进行验证。

如果我们更新第一个对象而不是整个对象呢?

   foo() {
      this.array[0].name = "foo";
   }
Run Code Online (Sandbox Code Playgroud)

? 这里没有必要使用trackBy

它在使用Subscription时特别有用,它通常看起来像我用array. 所以它看起来像:

   array = [];
   subscription: Subscription;

   ngOnInit(): void {
      this.subscription = this.fooService.getArray().subscribe(data => {
         this.array = data;
      });
   }

   identify(index, item) {
      return item.id;
   }
Run Code Online (Sandbox Code Playgroud)