¿Cuál es el ciclo de vida de un controlador AngularJS?

199

¿Alguien puede aclarar cuál es el ciclo de vida de un controlador AngularJS?

  • ¿Es un controlador un singleton, o creado / destruido a pedido?
  • Si es esto último, ¿qué desencadena la creación / destrucción del controlador?

Considere el siguiente ejemplo:

var demoApp = angular.module('demo')
  .config(function($routeProvider, $locationProvider) {
    $routeProvider
      .when('/home', {templateUrl: '/home.html', controller: 'HomeCtrl'})
      .when('/users',{templateUrl: '/users.html', controller: 'UsersCtrl'})
      .when('/users/:userId', {templateUrl: '/userEditor.html', controller: 'UserEditorCtrl'});
  });

demoApp.controller('UserEditorCtrl', function($scope, $routeParams, UserResource) {
  $scope.user = UserResource.get({id: $routeParams.userId});
});

p.ej:

En el ejemplo anterior, cuando navego /users/1, el usuario 1 se carga y se establece en $scope.

Luego, cuando navego /users/2, se carga el usuario 2. ¿Se UserEditorCtrlreutiliza la misma instancia o se crea una nueva instancia?

  • Si se trata de una nueva instancia, ¿qué desencadena la destrucción de la primera instancia?
  • Si se reutiliza, ¿cómo funciona esto? (es decir, el método para cargar los datos parece ejecutarse en la creación del controlador)
Marty Pitt
fuente

Respuestas:

227

Bueno, en realidad la pregunta es cuál es el ciclo de vida de un ngViewcontrolador.

Los controladores no son singletons. Cualquiera puede crear un nuevo controlador y nunca se autodestruyen. El hecho es que generalmente está vinculado al ciclo de vida de su alcance subyacente. El controlador no se destruye automáticamente cada vez que se destruye su alcance. Sin embargo, después de destruir un alcance subyacente, su controlador es inútil (al menos, por diseño, debería serlo).

Respondiendo a su pregunta específica, una ngViewdirectiva (al igual que la ngControllerdirectiva) siempre creará un nuevo controlador y un nuevo alcance cada vez que ocurra una navegación. Y el último alcance también será destruido .

Los "eventos" del ciclo de vida son bastante simples. Su "evento de creación" es la construcción de su propio controlador. Solo ejecuta tu código. Para saber cuándo se vuelve inútil ( "evento de destrucción" ), escuche el $destroyevento de alcance :

$scope.$on('$destroy', function iVeBeenDismissed() {
  // say goodbye to your controller here
  // release resources, cancel request...
})

Para ngViewespecíficamente, usted es capaz de saber cuando el contenido se carga a través del evento alcance $viewContentLoaded:

$scope.$on('$viewContentLoaded', function readyToTrick() {
  // say hello to your new content here
  // BUT NEVER TOUCHES THE DOM FROM A CONTROLLER
});

Aquí hay un Plunker con una prueba de concepto (abra la ventana de su consola).

Caio Cunha
fuente
10
Hoy en día el código que destruye el alcance $ vive en github.com/angular/angular.js/blob/… . Muy útil, gracias!
w00t
44
viewContentLoaded solo funciona si usa un tiempo de espera porque se despacha justo antes de que se cargue la plantilla ... los documentos dicen lo contrario, pero se refieren a raw template: "HTML STRING"cuando se trata de un archivo de plantilla que se carga de forma asíncrona.
user3338098