AngularJs 的 ng-repeat 让我们非常方便的遍历数组生成 Dom 元素,但是使用不当也会有性能问题。
在项目中我们使用 ng-repeat 加载完一个列表后,如果再次请求数据,然后过滤列表,代码可能会这么写:
<html> <head> <title>AngularJs ng-repeat实例</title> </head> <body> <h1>AngularJs ng-repeat实例</h1> <div ng-controller="Test"> <button ng-click="request()">请求新数据</button> <div ng-repeat="user in users"> {{user.name}} </div> </div> <script src="jquery-1.8.3.js"></script> <script src="angular1.2.9.js"></script> <script src="app.js"></script> </body> </html>
Controller 的代码:
var app = angular.module('myModule', []); app.controller('Test', ['$scope', function($scope) { var users = []; for (var i = 0; i < 10; i++) { users[i] = { id: i, name: "User: " + i }; } $scope.users = users; $scope.request = function () { var newUsers = []; for (var i = 0; i < 10; i++) { newUsers[i] = { id: i, name: "NewUser: " + i }; } // 从服务器加载新数据 var result = newUsers; // 直接重新赋值给 users $scope.users = result; }; }]); angular.element(document).ready(function() { angular.bootstrap(document,['myModule']); });
查看 ng-repeat 的源码可以发现,当 ng-repeat 的数组被替换时, 它默认并不会重新利用已有的 Dom 元素,而是直接将其全部删除并重新生成新的数组 Dom 元素:
// 将上次生成的所有 dom 移除 for (key in lastBlockMap) { if (lastBlockMap.hasOwnProperty(key)) { block = lastBlockMap[key]; elementsToRemove = getBlockElements(block.clone); $animate.leave(elementsToRemove); forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; }); block.scope.$destroy(); } }
Dom 的频繁操作是非常不友好的,为什么 ng-repeat 不能利用已有的 dom 元素去更新数据呢?因为你没有把数组元素的标识属性告诉它,那么两次替换的时候它就没办法追踪了,稍微修改如上实例,我们Debug可以看到 ng-repeat 往数组里每个元素加了一个$$hashKey的属性:
var app = angular.module('myModule', []); app.controller('Test', ['$scope', function($scope) { var users = []; for (var i = 0; i < 10; i++) { users[i] = { id: i, name: "User: " + i }; } $scope.users = users; $scope.request = function () { var newUsers = []; for (var i = 0; i < 10; i++) { newUsers[i] = { id: i, name: "NewUser: " + i }; } // 从服务器加载新数据 var result = newUsers; $scope.oldJsonStr = JSON.stringify($scope.users); $scope.oldToJson = angular.toJson($scope.users); // 直接重新赋值给 users $scope.users = result; }; }]); angular.element(document).ready(function() { angular.bootstrap(document,['myModule']); });
Debug跟踪如下:
这个 key 是由 Angular 内部的 nextUid() 方法生成,类似数据库自增,但是是使用字符串。
现在我们明白了,因为每次替换数组都会导致 ng-repeat 为每个元素生成一个新 key, 所以根本没办法重用已有的 Dom 元素,那么我们可以使用下面track by语法来避免这个问题:
<html> <head> <title>AngularJs ng-repeat实例</title> </head> <body> <h1>AngularJs ng-repeat实例</h1> <div ng-controller="Test"> <button ng-click="request()">请求新数据</button> <div ng-repeat="user in users track by user.id"> {{user.name}} </div> <div> <div>JSON.stringify:{{oldJsonStr}}</div> <div>angular.toJson:{{oldToJson}}</div> </div> </div> <script src="jquery-1.8.3.js"></script> <script src="angular1.2.9.js"></script> <script src="app.js"></script> </body> </html>
这样 ng-repeat 就用将其缓存起来啦,当然可能你的数组元素没有一个标识属性,如果元素数量不多那么可以接受,不然还是建议你手动为其生成一个标识属性。
另外,通过如上在页面上输出JSON.stringify、angular.toJson进一步来看不使用track by和使用track by的效果:
a.不使用track by
b.使用track by
如上运行结果也说明:因为ng-repeat会在数组对象内部添加$$hashkey属性,使用JSON.stringify序列化不会过滤$$hashkey属性,angular.toJson则会过滤掉。
参考文章:http://www.cnblogs.com/MigCoder/p/3930264.html?utm_source=tuicool&utm_medium=referral
相关推荐
然而,在使用`ng-repeat`进行渲染的过程中,有时候开发者会遇到无法直接获取到这些DOM对象的问题。这种情况经常发生的原因包括AngularJS的编译和链接机制以及其运行时的异步特性。 首先,要理解AngularJS的双向数据...
在AngularJS中,`ng-repeat`是一个非常重要的指令,它用于循环遍历数据集合,并将每个元素渲染到...在实际项目中,需要注意避免因为Scope的继承导致的意外数据共享问题,以及合理利用`ng-repeat`的特性来优化用户体验。
AngularJs 的 ng-repeat 让我们非常方便的遍历数组生成 Dom 元素,但是使用不当也会有性能问题。下面给大家分享在项目中使用ng-repeat指令实现下拉框。 1、问题背景 select下拉框里option组装成下拉框,这里利用ng-...
大数据量的`ng-repeat`可能导致性能问题。使用`$watch`优化、惰性加载、虚拟滚动等技术可以提升性能。 10. **自定义迭代器** 通过`as`关键字,我们可以自定义迭代器的名字,例如`item as myItem`。 总结,`ng-...
在讲解AngularJS中ng-repeat指令的使用实例之前,我们需要先对AngularJS和ng-repeat指令做一个基本的了解。 AngularJS是Google开发的一个开源的前端JavaScript框架,用来开发动态网页。它通过HTML的扩展(即所谓的...
值得注意的是,ng-repeat在性能方面有一些考虑,尤其是当处理大量数据时,应当注意避免对DOM进行过度的操作,这可能会导致性能下降。 AngularJS的ng-repeat还提供了更多的高级功能,比如嵌套的ng-repeat来处理多维...
总之,当在AngularJS中遇到ng-repeat不更新视图的问题时,关键是检查是否有为ng-repeat提供合适的track by表达式。通过指定一个唯一的标识符,AngularJS可以更加准确地检测到数组元素的变化,从而更新视图,确保数据...
在AngularJS框架中,ng-repeat指令的基本语法格式如下: ```html <element ng-repeat="expression"> ``` 这里,`<element>`代表任意HTML标签,`expression`代表表达式,用于指定要循环的数组或对象。AngularJS通过...
在“ng-repeat demo”中,可能会展示如何使用`ng-repeat`与AngularJS的其他特性,如`ng-if`、`ng-switch`、`ng-init`等结合使用,以及如何处理嵌套循环和过滤数据。此外,可能还会涉及到`track by`关键字,它用于...
在AngularJS中,`ng-repeat`是一个非常重要的指令,用于迭代数组或对象集合,并在DOM中生成对应的元素。然而,当遍历的数据源包含重复项时,`ng-repeat`会抛出一个错误:“Duplicates in a repeater are not allowed...
quick-ng-repeat, 一个更快速的替换AngularJS的重复指令 的AngularJS指令更快速地列出渲染特性浅表表( ngRepeat使用深表)动画支持特殊服务,使列表呈现在摘要循环之外在重compited列表中平滑滚动( 检查示例)大约 200...
1. **实时视图绑定**:ng-inspector能够实时显示AngularJS应用中的数据绑定,包括双向数据绑定(`ng-model`)、表达式(`{{ }}`)以及指令(如`ng-repeat`、`ng-if`等)的状态,这对于理解数据流和视图更新非常有...
<option ng-repeat="item in items" value="{{item.id}}">{{item.name}} ``` 在这里,`items`是一个包含所有可选项的对象数组,`selectedItems`将保存用户选择的项。 2. **数据绑定**:在你的控制器中,初始化...
本文将详细介绍如何在AngularJS的`ng-repeat`中实现这一功能。 首先,我们可以创建一个自定义过滤器(filter)来处理这个问题。过滤器是AngularJS中用于转换数据的一种机制,可以用于格式化日期、货币,或者如本文...
需要注意的是,虽然ng-if指令在实现筛选时非常方便,但它也会对性能产生一定影响,因为它会导致ng-repeat创建的所有元素先被渲染到内存中,然后ng-if再决定哪些元素被真正添加到DOM中。如果筛选条件非常严格,或者...
值得注意的是,错误提示“[ngRepeat:dupes]Duplicates in a repeater are not allowed”中提到的“duplicates are not allowed”,强调了在AngularJS中使用ng-repeat时必须确保生成的列表元素具有唯一性。...
需要注意的是,在使用ng-repeat时,`track by`子句可以用来指定如何跟踪数组中元素的唯一性,这对于处理对象数组尤其重要,但对于基本类型的数组来说,AngularJS默认可以自动跟踪。不过,建议在可能引起性能问题的...
**注意事项**:使用 `ng-repeat` 时,注意不要在循环内部执行复杂的计算或者操作DOM元素,这可能会导致性能问题。 #### 二、动态绑定之 ng-model 标签 **功能概述**:`ng-model` 指令用于在表单元素与模型之间建立...