Javascript 什么是 AngularJS 中的“track by”,它是如何工作的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39640160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:46:04  来源:igfitidea点击:

What is "track by" in AngularJS and how does it work?

javascriptangularjsng-repeatangularjs-track-by

提问by xoxel

I don't really understand how track byworks and what it does.
My main goal is to use it with ng-repeatto add some precision.

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

回答by jusopi

Using track byto track strings & duplicate values

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

Normally ng-repeattracks each item by the item itself. For the given array objs = [ 'one', 'one', 2, 'five', 'string', 'foo'], ng-repeatattempts to track changes by each objin the ng-repeat="obj in objs". The problem is that we have duplicate values and angular will throw an error. One way to solve that is to have angular track the objects by other means. For strings, track by $indexis a good solution as you really haven't other means to track a string.

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

track by& triggering a digest & input focuses

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

You allude to the fact you're somewhat new to angular. A digest cycle occurs when angular performs an exhaustive check of each watched property in order to reflect any change to the correspodant view; often during a digest cycle it happens that your code modify other watched properties so the procedure needs to be performed again until angular detects no more changes.

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

For example: You click a button to update a model via ng-click, then you do somethings (i mean, the things you wrote in the callback to perform when an user makes a click), then angular trigger digest cycle in order to refresh the view. I'm not too articulate in explaining that so you should investigate further if that didn't clarify things.

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

So back to track by. Let's use an example:

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

  1. call a service to return an array of objects
  2. update an object within the array and save object
  3. after save service, depending on what the API returns, you may:
    1. replace the whole object OR
    2. update a value on the existing object
  4. reflect change in ng-repeatUI
  1. 调用服务以返回对象数组
  2. 更新数组中的对象并保存对象
  3. 保存服务后,根据 API 返回的内容,您可以:
    1. 替换整个对象或
    2. 更新现有对象的值
  4. 反映ng-repeatUI 的变化

How you track this object will determine how the UI reflects the change.

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

One of the most annoying UXs I've experienced is this. Say you have a table of objects, each cell has an input where you want to in-line edit those objects' properties. I want to change the value, then on-blur, save that object while moving to the next cell to edit while you might be waiting on the response. So this is an autosave type thing. Depending on how you setup your track bystatement, you may lose current focus (e.g. the field you're currently editing) when the response gets written back into your array of objects.

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

回答by Mohit Tanwani

When you add track byyou basically tell angular to generate a single DOM element per data object in the given collection.

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

You can track by $indexif your data source has duplicate identifiers.

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

If you do need to repeat duplicate items, you can substitute the default tracking behavior with your own using the track by expression.

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

Example:

例子:

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

Try to use the duplicate values in ng-repeat, you will get an error such as:

尝试使用 中的重复值ng-repeat,您将收到如下错误:

Error: ngRepeat:dupes Duplicate Key in Repeater

错误:ngRepeat:重复中继器中的重复键

To avoid this kind of problems you should use track by $index. For example:

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

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

Here is how you would get $indexin nested ng-repeat:

以下是您如何$index进入嵌套ng-repeat

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


Here are some resources that may help you:

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

回答by Elio Salvatore

You should use track byonly if you need to go against the default behaviour of ng-repeatwhich is to remove duplicate items.
You can track the items using the scope property $indexor specifying a custom function.

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

For instance:

例如:

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

Display all values of the array (42 is displayed twice).

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

For reference: https://docs.angularjs.org/api/ng/directive/ngRepeat

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