当集合发生变化时,ng-repeat是否会保留DOM元素或创建所有新元素?

时间:2023-02-04 03:45:43

I've seen a lot of questions about the order in which ng-repeat finishes compared to other directives or things going on in Angular land, but I haven't been able to find an answer to how exactly it accomplishes this.

我已经看到很多关于ng-repeat完成的顺序与其他指令或Angular上发生的事情相比的问题,但是我还没有找到答案来确定它是如何完成的。

I have two ideas of how it could work.

我有两个关于它如何工作的想法。

First Way: When ng-repeat's watcher triggers, it removes all elements it created from the DOM then creates all new elements in their place, even if many of those elements are the same (e.g. in the case of 1 item added to the backing array).

第一种方式:当ng-repeat的观察者触发时,它会删除它从DOM创建的所有元素,然后在其位置创建所有新元素,即使其中许多元素相同(例如,在支持数组中添加了1个项目的情况) )。

Second way: Since ng-repeat already keeps track of which elements go with which items in its backing collection, it simply removes the items that no longer exist in the collection and creates new elements for items that are new to the collection.

第二种方式:由于ng-repeat已经跟踪哪些元素与其后备集合中的哪些项目相关,因此它只删除集合中不再存在的项目,并为集合中新的项目创建新元素。


Which is it and why?

这是为什么?为什么?

1 个解决方案

#1


6  

It's the second way: Angular tries to be smart about creating/removing DOM elements:

这是第二种方式:Angular试图聪明地创建/删除DOM元素:

The ngRepeat directive provides a way to render a collection of items given a template. To do this, AngularJS compiles the given template and then clones it for each unique item in the collection. As the collection is mutated by the Controller, AngularJS adds, removes, and updates the relevant DOM elements as needed.

ngRepeat指令提供了一种在给定模板的情况下呈现项集合的方法。为此,AngularJS编译给定的模板,然后为集合中的每个唯一项克隆它。由于Controller对集合进行了变更,AngularJS会根据需要添加,删除和更新相关的DOM元素。

But, how does AngularJS know which actions to perform when? If you start to test the rendering, you'll discover that AngularJS doesn't brute force DOM creation; that is, it doesn't recreate the DOM for every rendering. Instead, it only creates a new DOM element when a completely new item has been introduced to the collection. If an existing item has been updated, AngularJS merely updates the relevant DOM properties rather than creating a new DOM node.

但是,AngularJS如何知道何时执行哪些操作?如果你开始测试渲染,你会发现AngularJS不会强行创建DOM;也就是说,它不会为每次渲染重新创建DOM。相反,它只在将全新项目引入集合时才创建新的DOM元素。如果现有项已更新,AngularJS仅更新相关的DOM属性,而不是创建新的DOM节点。

This can still impact performance unnecessarily, i.e. when passing elements by-value in a collection (there's an excellent example of this in the blog post linked above). That's why Angular supports "track by" for ngRepeat since version 1.2: It's a way to help Angular decide when DOM creation is necessary:

这仍然会不必要地影响性能,即在集合中传递元素按值时(在上面链接的博客文章中有一个很好的例子)。这就是为什么Angular从版本1.2开始支持ngRepeat的“跟踪”:这是一种帮助Angular决定何时创建DOM的方法:

With this association in place, AngularJS will not $destroy and re-create DOM nodes unnecessarily. This can have a huge performance and user experience benefit.

有了这种关联,AngularJS就不会破坏并不必要地重新创建DOM节点。这可以带来巨大的性能和用户体验优势。

The official documentation states:

官方文件说明:

You can also provide an optional tracking function which can be used to associate the objects in the collection with the DOM elements. If no tracking function is specified the ng-repeat associates elements by identity in the collection.

您还可以提供可选的跟踪功能,该功能可用于将集合中的对象与DOM元素相关联。如果未指定跟踪功能,则ng-repeat按集合中的标识关联元素。

For example: item in items track by item.id is a typical pattern when the items come from the database. In this case the object identity does not matter. Two objects are considered equivalent as long as their id property is same.

例如:item by item中的项目是项目来自数据库时的典型模式。在这种情况下,对象标识无关紧要。只要两个对象的id属性相同,它们就被认为是等价的。

#1


6  

It's the second way: Angular tries to be smart about creating/removing DOM elements:

这是第二种方式:Angular试图聪明地创建/删除DOM元素:

The ngRepeat directive provides a way to render a collection of items given a template. To do this, AngularJS compiles the given template and then clones it for each unique item in the collection. As the collection is mutated by the Controller, AngularJS adds, removes, and updates the relevant DOM elements as needed.

ngRepeat指令提供了一种在给定模板的情况下呈现项集合的方法。为此,AngularJS编译给定的模板,然后为集合中的每个唯一项克隆它。由于Controller对集合进行了变更,AngularJS会根据需要添加,删除和更新相关的DOM元素。

But, how does AngularJS know which actions to perform when? If you start to test the rendering, you'll discover that AngularJS doesn't brute force DOM creation; that is, it doesn't recreate the DOM for every rendering. Instead, it only creates a new DOM element when a completely new item has been introduced to the collection. If an existing item has been updated, AngularJS merely updates the relevant DOM properties rather than creating a new DOM node.

但是,AngularJS如何知道何时执行哪些操作?如果你开始测试渲染,你会发现AngularJS不会强行创建DOM;也就是说,它不会为每次渲染重新创建DOM。相反,它只在将全新项目引入集合时才创建新的DOM元素。如果现有项已更新,AngularJS仅更新相关的DOM属性,而不是创建新的DOM节点。

This can still impact performance unnecessarily, i.e. when passing elements by-value in a collection (there's an excellent example of this in the blog post linked above). That's why Angular supports "track by" for ngRepeat since version 1.2: It's a way to help Angular decide when DOM creation is necessary:

这仍然会不必要地影响性能,即在集合中传递元素按值时(在上面链接的博客文章中有一个很好的例子)。这就是为什么Angular从版本1.2开始支持ngRepeat的“跟踪”:这是一种帮助Angular决定何时创建DOM的方法:

With this association in place, AngularJS will not $destroy and re-create DOM nodes unnecessarily. This can have a huge performance and user experience benefit.

有了这种关联,AngularJS就不会破坏并不必要地重新创建DOM节点。这可以带来巨大的性能和用户体验优势。

The official documentation states:

官方文件说明:

You can also provide an optional tracking function which can be used to associate the objects in the collection with the DOM elements. If no tracking function is specified the ng-repeat associates elements by identity in the collection.

您还可以提供可选的跟踪功能,该功能可用于将集合中的对象与DOM元素相关联。如果未指定跟踪功能,则ng-repeat按集合中的标识关联元素。

For example: item in items track by item.id is a typical pattern when the items come from the database. In this case the object identity does not matter. Two objects are considered equivalent as long as their id property is same.

例如:item by item中的项目是项目来自数据库时的典型模式。在这种情况下,对象标识无关紧要。只要两个对象的id属性相同,它们就被认为是等价的。