`

AngularJs ng-repeat必须注意的性能问题

阅读更多

        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

  • 大小: 46.1 KB
  • 大小: 25.9 KB
  • 大小: 20.9 KB
分享到:
评论

相关推荐

    angularjs,ng-repeat循环渲染时,无法获取dom对象.pdf

    然而,在使用`ng-repeat`进行渲染的过程中,有时候开发者会遇到无法直接获取到这些DOM对象的问题。这种情况经常发生的原因包括AngularJS的编译和链接机制以及其运行时的异步特性。 首先,要理解AngularJS的双向数据...

    通过angularjs的ng-repeat指令看scope的继承关系

    在AngularJS中,`ng-repeat`是一个非常重要的指令,它用于循环遍历数据集合,并将每个元素渲染到...在实际项目中,需要注意避免因为Scope的继承导致的意外数据共享问题,以及合理利用`ng-repeat`的特性来优化用户体验。

    AngularJS使用ng-repeat指令实现下拉框

    AngularJs 的 ng-repeat 让我们非常方便的遍历数组生成 Dom 元素,但是使用不当也会有性能问题。下面给大家分享在项目中使用ng-repeat指令实现下拉框。 1、问题背景 select下拉框里option组装成下拉框,这里利用ng-...

    AngularJS实战之ng-repeat的详细用法

    大数据量的`ng-repeat`可能导致性能问题。使用`$watch`优化、惰性加载、虚拟滚动等技术可以提升性能。 10. **自定义迭代器** 通过`as`关键字,我们可以自定义迭代器的名字,例如`item as myItem`。 总结,`ng-...

    Angularjs中ng-repeat的简单实例

    在讲解AngularJS中ng-repeat指令的使用实例之前,我们需要先对AngularJS和ng-repeat指令做一个基本的了解。 AngularJS是Google开发的一个开源的前端JavaScript框架,用来开发动态网页。它通过HTML的扩展(即所谓的...

    AngularJS ng-repeat遍历输出的用法

    值得注意的是,ng-repeat在性能方面有一些考虑,尤其是当处理大量数据时,应当注意避免对DOM进行过度的操作,这可能会导致性能下降。 AngularJS的ng-repeat还提供了更多的高级功能,比如嵌套的ng-repeat来处理多维...

    关于AngularJS中ng-repeat不更新视图的解决方法

    总之,当在AngularJS中遇到ng-repeat不更新视图的问题时,关键是检查是否有为ng-repeat提供合适的track by表达式。通过指定一个唯一的标识符,AngularJS可以更加准确地检测到数组元素的变化,从而更新视图,确保数据...

    AngularJS基础 ng-repeat 指令简单示例

    在AngularJS框架中,ng-repeat指令的基本语法格式如下: ```html &lt;element ng-repeat="expression"&gt; ``` 这里,`&lt;element&gt;`代表任意HTML标签,`expression`代表表达式,用于指定要循环的数组或对象。AngularJS通过...

    ng-repeat demo

    在“ng-repeat demo”中,可能会展示如何使用`ng-repeat`与AngularJS的其他特性,如`ng-if`、`ng-switch`、`ng-init`等结合使用,以及如何处理嵌套循环和过滤数据。此外,可能还会涉及到`track by`关键字,它用于...

    AngularJS的浏览器插件ng-inspector.zip

    1. **实时视图绑定**:ng-inspector能够实时显示AngularJS应用中的数据绑定,包括双向数据绑定(`ng-model`)、表达式(`{{ }}`)以及指令(如`ng-repeat`、`ng-if`等)的状态,这对于理解数据流和视图更新非常有...

    AngularJS ng-repeat指令中使用track by子语句解决重复数据遍历错误问题

    在AngularJS中,`ng-repeat`是一个非常重要的指令,用于迭代数组或对象集合,并在DOM中生成对应的元素。然而,当遍历的数据源包含重复项时,`ng-repeat`会抛出一个错误:“Duplicates in a repeater are not allowed...

    quick-ng-repeat, 一个更快速的替换AngularJS的重复指令.zip

    quick-ng-repeat, 一个更快速的替换AngularJS的重复指令 的AngularJS指令更快速地列出渲染特性浅表表( ngRepeat使用深表)动画支持特殊服务,使列表呈现在摘要循环之外在重compited列表中平滑滚动( 检查示例)大约 200...

    angularjs ui-select2 多选下拉所需资源文件

    &lt;option ng-repeat="item in items" value="{{item.id}}"&gt;{{item.name}} ``` 在这里,`items`是一个包含所有可选项的对象数组,`selectedItems`将保存用户选择的项。 2. **数据绑定**:在你的控制器中,初始化...

    Angularjs的ng-repeat中去除重复数据的方法

    本文将详细介绍如何在AngularJS的`ng-repeat`中实现这一功能。 首先,我们可以创建一个自定义过滤器(filter)来处理这个问题。过滤器是AngularJS中用于转换数据的一种机制,可以用于格式化日期、货币,或者如本文...

    AngularJS使用ng-repeat和ng-if实现数据的删选显示效果示例【适用于表单数据的显示】

    需要注意的是,虽然ng-if指令在实现筛选时非常方便,但它也会对性能产生一定影响,因为它会导致ng-repeat创建的所有元素先被渲染到内存中,然后ng-if再决定哪些元素被真正添加到DOM中。如果筛选条件非常严格,或者...

    AngularJS 使用ng-repeat报错 [ngRepeat:dupes]

    值得注意的是,错误提示“[ngRepeat:dupes]Duplicates in a repeater are not allowed”中提到的“duplicates are not allowed”,强调了在AngularJS中使用ng-repeat时必须确保生成的列表元素具有唯一性。...

    AngularJS使用ng-repeat遍历二维数组元素的方法详解

    需要注意的是,在使用ng-repeat时,`track by`子句可以用来指定如何跟踪数组中元素的唯一性,这对于处理对象数组尤其重要,但对于基本类型的数组来说,AngularJS默认可以自动跟踪。不过,建议在可能引起性能问题的...

    AngularJS 最常用的八种功能

    **注意事项**:使用 `ng-repeat` 时,注意不要在循环内部执行复杂的计算或者操作DOM元素,这可能会导致性能问题。 #### 二、动态绑定之 ng-model 标签 **功能概述**:`ng-model` 指令用于在表单元素与模型之间建立...

Global site tag (gtag.js) - Google Analytics