Cómo limitar el resumen angular para solo afectar / volver a renderizar un componente / directiva

Estaba desarrollando una aplicación / sitio angular, y solo ahora me di cuenta de que cada vez que se activa un modelo / resumen, hace que la página vuelva a reproducirse, lo que parece un desperdicio y es lento.

¿Hay alguna manera de causar / limitar el resumen para que solo afecte a la directiva / controlador en el que se usa?

por ejemplo, si tengo una directiva de “reloj” con $ intervalo para contar milisegundos en una página

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

y el diseño de mi aplicación se veía así

  //<--gets rendered every 30ms some other html  // ^-- also gets rendered every 30ms  

¿Cómo puedo evitar que la directiva lenta se actualice a sí misma / su plantilla cada 30ms, y limite el intervalo de reloj a la directiva del reloj, ya que sé que no se usará en ninguna otra parte de la página? (esta no es mi aplicación real, solo una muestra para ilustrar mi pregunta)

Angular will (por lo general) re-renderizar todo en $rootScope.$digest() , que es llamado por $scope.$apply() , $interval , y así sucesivamente.

Sin embargo, hay una estrategia de optimización que puede aplicar solo para volver a procesar las partes aplicables (las actualizaciones de alta frecuencia).

Primero, separa tus vistas en diferentes ámbitos. Por ejemplo, el contador que se actualiza cada 30 ms podría estar en su propio controlador, separándolo del scope con la directiva pesada.

Luego, use un intervalo no angular (por ejemplo, setInterval() ) para actualizar su valor, y llame $scope.$digest() manualmente.

Por ejemplo:

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:

   

Interval counter: {{ counter }}

Heavy calc: {{ calc() }}

Plunker

En este caso, pretenda que calc() es la directiva pesada. Notarás que solo se evalúa una vez, no cada vez que se actualiza el contador. Sin embargo, si usa $interval , se actualizará cada vez que se actualice el contador.

Tenga en cuenta que debe usar $scope.$digest() – si usa $scope.$apply() $rootScope.$digest() $scope.$apply() , llamará a $rootScope.$digest() , que actualizará todo.

Lectura adicional aquí .