23

我真的不明白它是如何track by工作的以及它做了什么。
我的主要目标是使用它ng-repeat来增加一些精度。

4

4 回答 4

26

用于track by跟踪字符串和重复值

通常ng-repeat按项目本身跟踪每个项目。对于给定的数组,objs = [ 'one', 'one', 2, 'five', 'string', 'foo']尝试ng-repeat跟踪obj. ng-repeat="obj in objs"问题是我们有重复的值,而 angular 会抛出一个错误。解决该问题的一种方法是通过其他方式对对象进行角度跟踪。对于字符串,track by $index这是一个很好的解决方案,因为您确实没有其他方法来跟踪字符串。

track by& 触发摘要 & 输入焦点

你暗示你对角度有点陌生。当 Angular 对每个观察到的属性进行详尽的检查以反映对应视图的任何变化时,就会出现一个摘要循环;通常在摘要周期中,您的代码会修改其他监视的属性,因此需要再次执行该过程,直到 angular 检测到不再有更改。

例如:您单击一个按钮以通过 更新模型ng-click,然后执行某些操作(我的意思是,您在回调中编写的内容以在用户单击时执行),然后角触发摘要循环以刷新视图。我解释得不太清楚,所以如果这不能澄清事情,你应该进一步调查。

所以回到track by. 让我们举个例子:

  1. 调用服务以返回对象数组
  2. 更新数组中的对象并保存对象
  3. 保存服务后,根据 API 返回的内容,您可以:
    1. 替换整个对象或
    2. 更新现有对象的值
  4. 反映ng-repeatUI的变化

您如何跟踪此对象将决定 UI 如何反映更改。

我经历过的最烦人的用户体验之一就是这个。假设您有一个对象表,每个单元格都有一个输入,您希望在其中在线编辑这些对象的属性。我想更改值,然后on-blur在移动到下一个要编辑的单元格时保存该对象,而您可能正在等待响应。所以这是一个自动保存类型的东西。根据您设置track by语句的方式,当响应被写回您的对象数组时,您可能会失去当前焦点(例如,您当前正在编辑的字段)。

于 2016-09-22T13:33:24.770 回答
16

当您添加时,track by您基本上告诉 Angular 为给定集合中的每个数据对象生成一个 DOM 元素。

如果您track by $index的数据源具有重复的标识符,则可以。

如果您确实需要重复重复项目,您可以使用 track by 表达式替换默认的跟踪行为。

例子:

[{id:1,name:'one'}, {id:1,name:'one too'}, {id:2,name:'two'}]

尝试使用 中的重复值ng-repeat,你会得到一个错误,例如:

错误:ngRepeat:dupes Dupes Duplicate Key in Repeater

为避免此类问题,您应该使用track by $index. 例如:

<ul>
   <li ng-repeat="item in [1, 2, 3, 3] track by $index">
       {{ item }}
   </li>
</ul>

这是您进入$index嵌套的方式ng-repeat

<div ng-repeat="row in matrix">
    <div ng-repeat="column in row">
      <span>outer: {{$parent.$index}} inner: {{$index}}</span>
    </div>
</div>

以下是一些可能对您有所帮助的资源:

于 2016-09-22T13:24:32.610 回答
3

track by仅当您需要违反默认行为ng-repeat是删除重复项时才应使用。
您可以使用范围属性$index或指定自定义函数来跟踪项目。

例如:

<div ng-repeat="x in [42, 42, 43, 43] track by $index">
  {{x}}
</div>

显示数组的所有值(42 显示两次)。

供参考:https ://docs.angularjs.org/api/ng/directive/ngRepeat

于 2016-09-22T13:29:11.363 回答
0

假设我们有以下列表:

<ul>
   <li ng-repeat="item in items">
       {{ item }}
   </li>
</ul>

其中,项目具有以下结构:

{ 'id'=>id, 'name'=>name, 'description'=>description }

在我们希望对其进行更新之前,此列表中没有任何问题。为方便起见,我们将项目列表替换为另一个更新的项目列表,如下所示:

items = newItems;

但是,在这个新列表中,很少有项目发生变化。大多数项目保持不变。不幸的是,Angular 不知道如何识别我们的项目并将它们映射到相应的<li>元素,所以它只是删除所有元素并重新创建它们。在某些情况下,这是非常耗费性能的,这就是track by使用的地方。

通过将track by子句添加到元素

<li ng-repeat="item in items track by item.id">

我们正在通知 Angular,我们项目的唯一标识符是item.id. 现在 Angular 知道不重新创建所有项目,而只重新创建具有新 id 的项目,并且只更新其余的项目。在大多数情况下,性能改进是显着的。此外,就个人而言,我喜欢我可以在浏览器的开发人员工具上更轻松地监控我的项目,因为它们不会在我每次更新它们时消失。

于 2020-07-16T08:35:48.367 回答