AngularJs ng-repeat 必须注意的性能问题
AngularJs 的 ng-repeat 让我们非常方便的遍历数组生成 Dom 元素,但是使用不当也会有性能问题。
在项目中我们使用 ng-repeat 加载完一个列表后,如果再次请求数据,然后过滤列表,代码可能会这么写:
<div ng-controller="Test">
<button ng-click="request()">请求新数据</button>
<div ng-repeat="user in users">
{{user.name}}
</div>
</div>
Controller 的代码:
app.controller('Test', function($scope) {
var users = [];
for (var i = 0; i < 100; i++) {
users[i] = {
id: i,
name: "User: " + i
};
}
$scope.users = users;
$scope.request = function () {
// 从服务器加载新数据
var result = [];
// 直接重新赋值给 users
$scope.users = result;
};
});
查看 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 元素去更新数据呢?因为你没有把数组元素的标识属性告诉它,那么两次替换的时候它就没办法追踪了,我们可以看到 ng-repeat 往数组里每个元素加了一个 $$hashKey 的属性:

这个 key 是由 Angular 内部的 nextUid() 方法生成,类似数据库自增,但是是使用字符串。
现在我们明白了,因为每次替换数组都会导致 ng-repeat 为每个元素生成一个新 key, 所以根本没办法重用已有的 Dom 元素,那么我们可以使用下边的语法来避免这个问题:
<div ng-controller="Test">
<button ng-click="request()">请求新数据</button>
// 使用 track by 标识
<div ng-repeat="user in users track by user.id">
{{user.name}}
</div>
</div>
这样 ng-repeat 就用将其缓存起来啦,当然可能你的数组元素没有一个标识属性,如果元素数量不多那么可以接受,不然还是建议你手动为其生成一个标识属性。
AngularJs ng-repeat 必须注意的性能问题的更多相关文章
- Part 6 AngularJS ng repeat directive
ng-repeat is similar to foreach loop in C#. Let us understand this with an example. Here is what we ...
- part 4 AngularJS ng src directive
- Part 15 AngularJS ng init directive
The ng-init directive allows you to evaluate an expression in the current scope. In the following e ...
- table sorting–angularjs
1: <script type="text/javascript" ng:autobind 2: src="http://code.angularjs.org/0. ...
- [译]用AngularJS构建大型ASP.NET单页应用(三)
原文地址:http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single A ...
- 小程序组件化框架 WePY 在性能调优上做出的探究
作者:龚澄 导语 性能调优是一个亘古不变的话题,无论是在传统H5上还是小程序中.因为实现机制不同,可能导致传统H5中的某些优化方式在小程序上并不适用.因此必须另开辟蹊径找出适合小程序的调估方式. 本文 ...
- [AngularJS] AngularJS系列(1) 基础篇
目录 什么是AngularJS? 为什么使用/ng特性 Hello World 内置指令 内置过滤器 模块化开发 一年前开始使用AngularJS(以后简称ng),如今ng已经出2了.虽说2已完全变样 ...
- 从angularJS看MVVM
javascript厚积薄发走势异常迅猛,导致现在各种MV*框架百家争雄,MVVM从MVC演变而来,为javascript注入了全新的活力.我工作的业务不会涉及到angularJS[ng]这么重量级的 ...
- angularJS看MVVM
从angularJS看MVVM javascript厚积薄发走势异常迅猛,导致现在各种MV*框架百家争雄,MVVM从MVC演变而来,为javascript注入了全新的活力.我工作的业务不会涉及到a ...
- js架构设计模式——从angularJS看MVVM
javascript厚积薄发走势异常迅猛,导致现在各种MV*框架百家争雄,MVVM从MVC演变而来,为javascript注入了全新的活力.我工作的业务不会涉及到 angularJS[ng] 这么重量 ...
随机推荐
- Spring相框:AOP详细说明
AOP中国的名字叫做面向方面编程.这个名字是很形象.因为你真的可以把像面包切系统.并直接增加面包的修改.科而异,对整个系统,小到一定的方法. AOP它有什么用?有关示例,各组分可以含有安全.事务.,A ...
- Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质
原文:Linux内核分析(六)----字符设备控制方法实现|揭秘系统调用本质 Linux内核分析(六) 昨天我们对字符设备进行了初步的了解,并且实现了简单的字符设备驱动,今天我们继续对字符设备的某些方 ...
- .net卸载程序制作
原文:.net卸载程序制作 方法一: 在打包项目中添加文件msiexec.exe(一般在c:\windows\system32(系统目录中)找到). 在文件系统视图中选择应用程序文件,在msiexec ...
- c# webbrowser 获取用户选中文字
原文:c# webbrowser 获取用户选中文字 最近一直被一个问题困扰,有一个文本框,一个webbrowser控件,一个上下文菜单, webbrowser 获取用户选中文字" tit ...
- Android Loader使用,屏幕解锁,重复荷载
正在使用AsyncTaskLoader时间.当手机被解锁,重复加载数据,码,如以下: static class CouponShopQueryLoader extends AsyncTaskLoade ...
- codeforces 438D
在大大推荐下这个标题不明的人做.而我的最后一个非常喜欢的段树,因此,愤怒出手.认为基本上相同.大值,当最大值小于取模时能够剪枝. 今后再遇到此类问题算是能攻克了 // file name: d.cpp ...
- 栈 <stack>
STL: pop:完成的仅仅是移除最顶端的数据.如果访问最顶端的数据,需要使用top函数(这个操作通常也被称为peek). #include <stack> #include <cs ...
- [译文]c# /.Net 技巧: ToDictionary() and ToList()
前言: 有两个简单好用的LINQ扩展方法 ToDictionary() 和ToList(),你可能知道或不知道,但是它的的确确可以简化查询转化为集合的任务: 简介: LINQ和延迟执行 据你所认识的L ...
- 从头开始学JavaScript 笔记(一)——基础中的基础
原文:从头开始学JavaScript 笔记(一)--基础中的基础 概要:javascript的组成. 各个组成部分的作用 . 一.javascript的组成 javascript ECMASc ...
- JAVA简单Swing图形界面应用演示样例
JAVA简单Swing图形界面应用演示样例 package org.rui.hello; import javax.swing.JFrame; /** * 简单的swing窗体 * @author l ...