Angular - 嵌套$ scope将产生嵌套的$ watchers?

时间:2016-04-05 10:18:43

标签: javascript angularjs performance scope angularjs-ng-repeat

我遇到性能问题,我认为由于页面中有很多观察者(超过4000 !!)。该场景是ng-repeat中的一个(小的,约5个)项目列表,每个项目包含每周一天的另一个ng-repeat(所以7),并且在每天容器中有1或2个输入字段。每天的元素都有自己的范围和控制器,有些监视父级的属性,以便在子级更改时更新父级状态。所以有点复杂的情况...想象一个议程视图,其中每天作为一些输入字段或按钮更新主范围内的相同属性,如“10天选择/填充/点击”。

我从大约5000名观察者开始,现在减少到大约4000个删除一些过滤器并切换到翻译指定翻译(angular-translate)。

所以主要的问题是:

如何进一步减少观察人数?

是否每个儿童范围都继承了父母观察者,每个观察者产生7倍?如果我删除孩子的控制器,将作业留给父母(将子项目传递给函数),我会减少观察者的数量吗?这可能是一个解决方案吗?任何帮助都是值得赞赏的。

2 个答案:

答案 0 :(得分:1)

根据我们的经验,观察者数量不会引起速度问题。我们在一个大型应用程序开发的最后8个月遇到的性能问题是由于第三部分组件速度缓慢造成的。

例如,我们有一个带有两个拖放树的页面,其中有14.600个观察者(因为两棵树中的项目数量很大)。由于使用了组件angular-ui-tree,我们遇到了性能问题,并且我们减少了它们打开页面,大部分树都崩溃了。

我们无法更改该组件,因为它是唯一一个在树之间拖放功能的组件,但是在另一个我们有拖放的页面中。在简单列表之间我们尝试了这两个组件:angular-dragdropangular-drag-and-drop-lists。第一个有很多性能问题(大约有500个项目)而第二个运行真的非常快。在他关于github的文档中,"Why another drag & drop library?"部分你可以理解为什么它如此之快以及为什么另一个如此之慢。

所以,我可以推测第三部分的组件会给你带来真正的性能问题,而不是观察者。

在任何情况下,我们经常使用下面的支票给我们的观察者写信,除非需要,否则不要运行代码。

$scope.$watch('variableToWatch', function(newValue, oldValue) {
    if (newValue === oldValue) {
        return;
    }

    ... watcher code ...
}

从html减少观察者的另一种方法是使用one-time-binding。 例如:

<div ng-if="::vm.user.loggedIn"></div>

答案 1 :(得分:0)

与性能相关... - 我提出的一种模式是使用私有对象并分配函数的原型以便于访问。然后在任何函数,控制器,指令......你可以轻松访问其他函数,控制器,指令的原型。而不是使用观察者,您可以像事件循环一样使用此模式。而不是每个消化周期角度运行300+观察者。使用这种模式只会触发函数调用。

此模式的一个示例

&#13;
&#13;
var private = {} //accesable to entire app


var app = angular.module('some-app',[])
.controller('someCtrl',['$scope',someCtrl])
.directive('someDirective',someDirective);

function someCtrl($scope){
private.someCtrl = someCtrl.prototype



someCtrl.prototype.update = function(someDate){
//do something....
//access to someCtrl arguments  
  
  $scope.something = someDate
}


}

function someDirective(){

  var someCtrlProto = private.someCtrl;
return{
  link:function(scope ,elm ,attr){
  
    elm[0].addEventListener('click',fucntion(){
           someCtrlProto.update(someData) 
    
      });
      //or
    
    elm[0].addEventListener('click',someCtrlProto.update) //to trigger someCtrl.update from here
    }
  }
}
&#13;
&#13;
&#13;