即使有大量的DOM元素,也可以改善AngularJS的性能

Ste*_*ven 23 angularjs

我正在评估是否将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)

http://jsfiddle.net/j6DkW/1/

  • 谢谢阿尔乔姆.是的,在更多地愚弄之后,我同意问题在于ng-repeat主要是因为它使许多观察者都必须在摘要期间执行.我发现,如果我使用的客户指令没有添加数千个观察程序功能,那么滞后性就会大大提高. (3认同)

TGH*_*TGH 7

现在这是一个老问题,但我认为值得添加的是Angular(自v1.3起)现在支持一次时间绑定,这有助于减少摘要循环.我已经开发了一些应用程序,其中添加一次时间绑定大大减少了手表的数量,从而提高了性能.ng-repeat通常负责添加大量手表,因此您可以考虑在ng-repeat中添加一次时间绑定.

ng-repeat="i in ::list"
Run Code Online (Sandbox Code Playgroud)

以下是一些可用于避免添加不必要的手表的技术的摘要

http://www.syntaxsuccess.com/viewarticle/547a8ba2c26c307c614c715e