如何在angularjs

时间:2016-07-14 18:38:37

标签: angularjs

作为摘要周期,对变量进行脏检查,如果有100个范围变量,如果我更改了一个变量,那么它将运行所有变量的监视。

假设我有100个相互独立的范围模型变量。如果我在一个变量中进行更改,那么我不想检查所有其他99个变量。有没有办法做到这一点?如果是,怎么样?

3 个答案:

答案 0 :(得分:30)

令人惊讶的是,这通常不是问题,浏览器即使有数千个绑定也没有问题,除非表达式很复杂。 how many watchers are ok to have 的常见答案是 2000

解决方案:

AngularJS 1.3开始相当容易,因为现在 one-time 绑定在核心。

  1. 一次绑定变量。
  2. 我们可以使用一次性绑定(::)指令来阻止观察者观察不需要的变量。在这里,变量将只观看一次&之后它不会更新该变量。

    1. 手动停止摘要周期。
    2. HTML:

      <ul ng-controller="myCtrl">
        <li ng-repeat="item in Lists">{{lots of bindings}}</li>
      </ul>
      

      控制器代码:

      app.controller('myCtrl', function ($scope, $element) {
        $element.on('scroll', function () {
          $scope.Lists = getVisibleElements();
          $scope.$digest();
        });
      });
      

      $digest 期间,您只对Lists对象的更改感兴趣,而不是对单个项目的更改。然而,Angular仍会询问每个观察者的变化。

      stoppause摘要的指令:

      app.directive('stopDigest', function () {
        return {
          link: function (scope) {
            var watchers;
      
            scope.$on('stop', function () {
              watchers = scope.$$watchers;
              scope.$$watchers = [];
            });
      
            scope.$on('resume', function () {
              if (watchers)
                scope.$$watchers = watchers;
            });
          }
        };
      });
      

      现在,应更改控制器代码:

      <ul ng-controller="listCtrl">
        <li stop-digest ng-repeat="item in visibleList">{{lots of bindings}}</li>
      </ul>
      
      app.controller('myCtrl', function ($scope, $element) {
        $element.on('scroll', function () {
          $scope.visibleList = getVisibleElements();
      
          $scope.$broadcast('stop');
          $scope.$digest();
          $scope.$broadcast('resume');
        });
      });
      

      参考文档: https://coderwall.com/p/d_aisq/speeding-up-angularjs-s-digest-loop

      感谢。

答案 1 :(得分:5)

这是一个很好的问题,并突出了Angular 1.x的最大缺陷之一。几乎无法控制如何管理摘要周期。它意味着是一个黑盒子,对于大型应用程序,这可能会导致严重的性能问题。没有角度方式做你的建议,但有一些东西可以帮助你实现相同的目标(即只有一件事发生变化时,更好的表现摘要周期)。

我建议使用bind-notifier plugin。我与该项目没有任何关系,但我将它用于我自己的项目,并且取得了很大的成功。

背后的想法是,您可以指定某些绑定仅在特定事件被引发时被消化。

有多种使用插件的方法,但是我发现这个方法必须有效:

在模板文件中,使用特殊的bind-notifier语法指定绑定:

<div>{{:user-data-change:user.name}}</div>
<div>{{:job-data-change:job.name}}</div>

除非通知,否则大多数摘要周期都不会对这两个绑定进行脏检查。

在控制器中,当用户数据发生变化时,请通知绑定:

this.refreshUserData().then(() => {
  $scope.$broadcast('$$rebind::user-data-change');
});

(和job-data-changed类似)

这样,user.name的绑定只会在广播中检查。

要记住的一些事项:

  1. 这基本上颠覆了角度的一个主要优点(也是大型应用的核心弱点)。双向绑定通常意味着您不需要主动管理模型的更改,但有了这个,您就可以了。因此,我只建议将此用于应用程序中具有大量绑定并导致速度下降的部分。
  2. $emit$broadcast本身可能会影响效果,因此请尝试仅在$scope树的小部分(scope s,几乎没有孩子)上调用它们。
  3. 仔细查看文档,因为有几种方法可以使用该插件。选择最适合您应用的使用模式。

答案 2 :(得分:1)

这是在摘要周期中进行独占/条件检查的一个非常具体的用例,我认为没有分支/黑客攻击角度核心是不可能的。

我会考虑重构你是如何/你是$watching。也许使用ngModelController的{​​{1}}比$viewChangeListeners更合适?