如何在angularjs中手动停止摘要循环

Sun*_*arg 17 angularjs

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

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

Roh*_*dal 32

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

方案:

AngularJS 1.3由于one-time绑定现在处于核心状态,所以它相当容易.

  1. 一次绑定变量.

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

  1. 手动停止摘要循环.

HTML:

<ul ng-controller="myCtrl">
  <li ng-repeat="item in Lists">{{lots of bindings}}</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

控制器代码:

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

在此期间$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;
      });
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

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

<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');
  });
});
Run Code Online (Sandbox Code Playgroud)

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

谢谢.


And*_*erg 5

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

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

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

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

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

<div>{{:user-data-change:user.name}}</div>
<div>{{:job-data-change:job.name}}</div>
Run Code Online (Sandbox Code Playgroud)

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

在您的控制器中,当用户数据发生更改时,请通知绑定,如下所示:

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

(和类似的job-data-changed)

有了这个,user.name只会在广播上检查绑定.

要记住以下几点:

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