我正在评估是否将AngularJS用于Web项目,我担心我需要实现的功能的性能.我想知道是否有更好的方法来实现我在AngularJS中尝试的功能.
从本质上讲,在我看来,AngularJS对事件做出反应的时间取决于页面中DOM元素的数量,即使DOM元素没有被主动更改等等.我猜这是因为$ digest函数正在遍历整个DOM ..至少从我的实验来看,似乎就是这种情况.
这是游戏场景(这不是我真正想要做的,但足够接近测试目的).
当我将鼠标悬停在它上面时,我想让angularJS突出显示一个单词.但是,随着页面中单词数量的增加,当您将鼠标悬停在单词上时以及实际突出显示单词时,延迟时间会更长.
显示这个的jsfiddle:http: //jsfiddle.net/czerwin/5qFzg/4/
(信用:此代码基于Peter Bacon Darwin在AngularJS论坛上的帖子).
这是HTML:
<div ng-app="myApp">
<div ng-controller="ControllerA">
<div >
<span ng-repeat="i in list" id="{{i}}" ng-mouseover='onMouseover(i)'>
{{i}},
</span>
<span ng-repeat="i in listB">
{{i}},
</span>
</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
这是javascript:
angular.module('myApp', [])
.controller('ControllerA', function($scope) {
var i;
$scope.list = [];
for (i = 0; i < 500; i++) {
$scope.list.push(i);
}
$scope.listB = [];
for (i = 500; i < 10000; i++) {
$scope.listB.push(i);
}
$scope.highlightedItem = 0;
$scope.onMouseover = function(i) {
$scope.highlightedItem = i;
};
$scope.$watch('highlightedItem', function(n, o) {
$("#" + o).removeClass("highlight");
$("#" + n).addClass("highlight");
});
});
Run Code Online (Sandbox Code Playgroud)
注意事项: - 是的,我正在使用jquery来进行DOM操作.我走这条路是因为这是一种注册观察者的方法.如果我纯粹在angularJS中这样做,我将不得不为每个跨度注册一个鼠标悬停处理程序,这似乎也使页面变慢. - 我也在纯jquery中实现了这种方法,性能很好.我不相信这是让我放慢速度的jquery电话. - 我只有前500个单词才能有id和类来验证它真的只是有更多的DOM元素似乎会减慢它们(而不是可能受操作影响的DOM元素).
Mar*_*her 13
尽管已经有一个公认的答案,但我认为理解为什么angularJS对你提供的代码反应如此之慢很重要.实际上angularJS并不是很慢,有很多DOM元素,在这种情况下,由于你在列表中的每个项目上注册了ng-mouseover指令,因此它很慢.ng-mouseover指令注册一个onmouseover事件监听器,每次触发监听器函数时,都会执行一个ng.$ apply(),它运行$ diggest脏比较检查并遍历所有监视和绑定.
简而言之:每次元素悬停时,内部
角度脏比较检查可能会消耗1-6毫秒(取决于绑定的数量,您已建立).不好 :)
那是相关的angularJS实现:
var ngEventDirectives = {};
forEach('click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
function(name) {
var directiveName = directiveNormalize('ng-' + name);
ngEventDirectives[directiveName] = ['$parse', function($parse) {
return {
compile: function($element, attr) {
var fn = $parse(attr[directiveName]);
return function(scope, element, attr) {
element.on(lowercase(name), function(event) {
scope.$apply(function() {
fn(scope, {$event:event});
});
});
};
}
};
}];
}
);
Run Code Online (Sandbox Code Playgroud)
实际上,为了突出显示悬停的文本,您可能只会使用CSS:
.list-item:hover {
background-color: yellow;
}
Run Code Online (Sandbox Code Playgroud)
对于较新的Angular版本,您的代码可能会运行得更快.对于角度版本1.3,有一次绑定操作符::它将从摘要循环中排除一次绑定的变量.有数千个项目,被排除将显着减少消化负荷.
与ECMAScript 6一样,angular可以使用Observe类,这将使脏比较检查完全过时.因此,单个鼠标悬停将在单个事件回调内部产生,不再应用或挖掘.全部都带有原始代码.当Angular将这个应用时,我不知道.我想在2.0.
Art*_*tem 10
我认为解决性能问题的最佳方法是避免在这种情况下使用高级抽象(AngularJS ng-repeat和所有相应的背景魔法).AngularJS不是一个银弹,它与低级库完美配合.如果您喜欢文本块中的此类功能,则可以创建一个指令,该指令将成为文本的容器并封装所有低级逻辑.自定义指令的示例,它使用了fontsjs jquery插件:
angular.module('myApp', [])
.directive('highlightZone', function () {
return {
restrict: 'C',
transclude: true,
template: '<div ng-transclude></div>',
link: function (scope, element) {
$(element).lettering('words')
}
}
})
Run Code Online (Sandbox Code Playgroud)
现在这是一个老问题,但我认为值得添加的是Angular(自v1.3起)现在支持一次时间绑定,这有助于减少摘要循环.我已经开发了一些应用程序,其中添加一次时间绑定大大减少了手表的数量,从而提高了性能.ng-repeat通常负责添加大量手表,因此您可以考虑在ng-repeat中添加一次时间绑定.
ng-repeat="i in ::list"
Run Code Online (Sandbox Code Playgroud)
以下是一些可用于避免添加不必要的手表的技术的摘要
http://www.syntaxsuccess.com/viewarticle/547a8ba2c26c307c614c715e
| 归档时间: |
|
| 查看次数: |
18923 次 |
| 最近记录: |