如何使用angular 2的内部跟踪

如何使用angular 2的内部跟踪,angular,ngfor,angularjs-track-by,Angular,Ngfor,Angularjs Track By,尝试了我能猜到的每一种语法都不能让它工作 <!--- 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> <

尝试了我能猜到的每一种语法都不能让它工作

<!--- 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 | json}}
{{post | json}}
{{post | json}}
{{post | json}}
{{post | json}}
唯一对我有效的方法是

  • 在控制器类中创建方法

    识别(索引,职位:职位){ 返回邮政编码 }

  • 
    

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

    正如@Eric comment中指出的那样,经过大量阅读和练习,下面是如何在angular2中使用trackBy

  • 首先你需要知道它与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>
    
    和angular的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 
         }
    
    }
    
    @Page({
    模板:`
    
      {{post.data}
    ` }) 导出类HomeworkAddStudentsPage{ 职位:阵列; 构造函数(){ this.posts=[{id:1,数据:'post with id 1'}, {id:2,数据:'post with id 2'}]; } 识别(索引、项目){ //不管您需要做什么,只要在循环中找到项目的唯一标识符,我就返回对象id。 返回邮政编码 } }
    trackBy可以使用callback的名称,它将为我们调用它,并提供两个参数:循环的索引和当前项

    为了实现与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};
    });
    
  • 应用程序控制器(功能($scope){ $scope.identify=函数(索引,项){return item.id}; });
    正如您已经认识到的,使用函数是在Angular 2中使用trackBy
    的唯一方法

    <ion-card *ngFor="#post of posts;trackBy:identify"></ion-card>
    
    
    
    官方文件指出


    关于
    的所有其他信息都是错误的。从Angular 2.4.1开始,这也会在应用程序中引发错误。

    trackBy背后的概念:

  • angular的
    ngFor
    通过跟踪对象标识自动优化修改/创建/删除对象的显示。 因此,如果您在列表中创建所有新对象,然后使用
    ngFor
    ,它将呈现整个列表

  • >P>让我们考虑一个场景,尽管所有的代码> ngOb/<代码>优化,但是渲染仍然需要时间。在这种情况下,我们使用
    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>
    
    
    Angular 2.1.2+TypeScript初学者工具包
    System.import('app')
    .catch(console.error.bind(console));
    加载。。。
    
    除了其他人的答案之外,我只想添加几个示例(Angular 2+),以明确trackBy的使用

    从文件:

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

    请在此处阅读更多信息:

    举个例子可以更好地解释这一点

    应用程序组件.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;
       }
    
    让我们使用
    *ngFor
    数组显示为3个div

    app.component.html

    无trackBy的
    *ngFor
    示例:

    <div *ngFor="let e of array;">
       {{e.id}} - {{e.name}}
    </div>
    <button (click)="foo()">foo</button>
    
    <div *ngFor="let e of array; trackBy: identify">
       {{e.id}} - {{e.name}}
    </div>
    <button (click)="foo()">foo</button>
    
    如果我们点击
    foo
    按钮会发生什么

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

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

    → 此处无需使用
    trackBy

    它在使用订阅时特别有用,订阅通常看起来像我用
    数组
    设计的。所以看起来是这样的:

       array = [];
       subscription: Subscription;
    
       ngOnInit(): void {
          this.subscription = this.fooService.getArray().subscribe(data => {
             this.array = data;
          });
       }
    
       identify(index, item) {
          return item.id;
       }
    

    你能告诉我trackBy在ngFor中的用途吗?Eric的答案似乎很好。@micronyks它允许您将一个函数传递给
    *ngFor
    ,该函数将
    ngFor
    转发给
    https://angular.io/docs/ts/latest/api/core/IterableDifferFactory-interface.html
    (但我还不知道这种差异是如何工作的)
    https://angular.io/docs/ts/latest/api/core/IterableDifferFactory-interface.html‌​ 没有找到。还有其他链接吗?我仍然不清楚trackBy的干净用法。如果这里有人在
    *ngFor
    中发布trackBy用法的示例,我会非常有帮助。我认为“trackBy:post?.id”不起作用。在我的例子中,子元素的状态丢失。一个单独的trackBy函数可以工作(但绝对不方便)。顺便说一句,elvis操作符本身表明出了问题。如果它能工作,那么您就不必在这里使用它(除非集合项可以为null)。我确认,trackBy只与函数一起工作,它与“post?.id”没有错误,但在这种情况下它将与trackBy“null”匹配(您可以检查html并看到),这意味着它根本不跟踪,除了@Olivier comment外,你能不能更新你的帖子以避免对新用户产生误导?你只是看不到一个错误@Zalaboza。从Angular 2.4.1开始,使用*ngFor=“#post of posts;trackBy:post?.id”将抛出一个错误,因为trackBy只接受函数right@Zalaboza,只允许函数,请更新您的帖子。此处讨论:@Zalaboza请您更新您的答案,其中
    trackBy:post?.id
    已被确认无效。不确定为什么您有一个既不运行也没有trackBy示例的“运行示例”,但出于trackBy背后的原因,+1。这只是为了提高性能。@Rap看起来很多
    <div *ngFor="let e of array; trackBy: identify">
       {{e.id}} - {{e.name}}
    </div>
    <button (click)="foo()">foo</button>
    
       foo() {
          this.array[0].name = "foo";
       }
    
       array = [];
       subscription: Subscription;
    
       ngOnInit(): void {
          this.subscription = this.fooService.getArray().subscribe(data => {
             this.array = data;
          });
       }
    
       identify(index, item) {
          return item.id;
       }