如何将角度摘要限制为仅影响/重新渲染一个组件/指令

时间:2015-06-16 19:41:38

标签: javascript html angularjs

我正在开发一个有角度的app / site,现在才意识到无论何时触发模型更改/摘要,都会导致整个页面重新渲染,这看起来很浪费而且很慢。

是否有办法使/限制摘要仅影响其使用的指令/控制器。

例如,如果我有一个"时钟"带有$ interval的指令,用于计算页面上的毫秒数

$scope.page_stats = {"ms_on_page": 0};
$interval(function() {
    $scope.page_stats.ms_on_page+= 30;
}, 30);

我的应用布局看起来像这样

<body>
    <clock-directive></clock-directive>//<--gets rendered every 30ms
    some other html
    <some-slow-render-directive></some-slow-render-directive>
    // ^-- also gets rendered every 30ms
</body>

如何阻止慢指令每30ms更新一次自身/它的模板,并将时钟间隔摘要限制为时钟指令,因为我知道它不会在页面的任何其他部分使用。 (这不是我的实际应用,只是一个示例来说明我的问题)

1 个答案:

答案 0 :(得分:7)

Angular会(通常)重新呈现$rootScope.$digest()上的所有内容,由$scope.$apply()$interval调用,依此类推。

但是,一种优化策略,您只能重新渲染适用的部分(高频更新)。

首先,将您的观点分成不同的范围。例如,每30毫秒更新一次的计数器可以在自己的控制器中,使用重指令将其与范围分开。

然后,使用非角度间隔(例如setInterval())更新您的值,并手动调用$scope.$digest()

例如:

JS:

app.controller('MainCtrl', function($scope, $interval) {
  // this is our "heavy" calculation function
  // it displays a Unix timestamp, which should change
  // every second if the function is continously executed
  $scope.calc = function() {
    // get time in seconds
    return Math.floor(new Date().getTime() / 1000);
  };
});

app.controller('ChildCtrl', function($scope, $interval) {
  $scope.counter = 0;

  // don't use $interval, it'll call $rootScope.$apply()
  // uncomment this and comment the setInterval() call
  // to see the problem
  //$interval(function() { $scope.counter++; }, 1000);

  setInterval(function() {
    $scope.counter++;

    // digest only our scope, without re-rendering everything
    $scope.$digest();
  }, 1000);
});

HTML:

<body ng-controller="MainCtrl">
  <!-- pretend this is our calculation that occurs often -->
  <p ng-controller="ChildCtrl">Interval counter: {{ counter }}</p>

  <!-- pretend this is our heavy calculation that we don't want to occur often -->
  <p>Heavy calc: {{ calc() }}</p>
</body>

Plunker

在这种情况下,假装calc()是重指令。您会注意到它只评估过一次,而不是每次计数器更新时。但是,如果您使用$interval,则每次计数器更新时都会更新。

请注意,必须使用$scope.$digest() - 如果您使用$scope.$apply(),则会调用$rootScope.$digest(),这将更新所有内容。

进一步阅读here