如何在ngFor angular 2中使用track

问题描述 投票:44回答:4

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

<!--- 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>

对我有用的唯一方法是

  1. 在控制器类中创建方法 识别(索引,帖子:帖子){return post.id}

<ion-card *ngFor="#post of posts;trackBy:identify">
</ion-card>

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

angular ngfor angularjs-track-by
4个回答
78
投票

正如在@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>

在这里你问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"

与角1相同

ng-repeat="post in posts track by post.id"

用法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 
     }

}

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};
});

9
投票

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

<ion-card *ngFor="#post of posts;trackBy:identify"></ion-card>

官方文件说明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开始,这也会在应用程序中引发错误。


2
投票

trackBy背后的概念:

  1. 角度的ngFor通过跟踪对象标识自动优化修改/创建/删除对象的显示。因此,如果您在列表中创建所有新对象然后使用ngFor,它将呈现整个列表。
  2. 让我们考虑一个场景,尽管所有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/[email protected]/dist/zone.js"></script>
    <script src="https://unpkg.com/[email protected]/Reflect.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/system.js"></script>
    <script src="https://unpkg.com/[email protected]/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>

-5
投票

这个简单的解决方案适合我的场景

<ion-card *ngFor="let post of posts;let i = index"> 
    {{i+1}}
</ion-card>

编辑:正如Jeremy Thille所示,你应该使用let而不是#,因为在最新版本的Angular2中不推荐使用#

© www.soinside.com 2019 - 2024. All rights reserved.