Jaki jest cykl życia kontrolera AngularJS?

199

Czy ktoś może wyjaśnić, jaki jest cykl życia kontrolera AngularJS?

  • Czy kontroler jest singletonem, czy też jest tworzony / niszczony na żądanie?
  • Jeśli to drugie, co powoduje utworzenie / zniszczenie kontrolera?

Rozważ poniższy przykład:

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});
});

na przykład:

W powyższym przykładzie, kiedy nawiguję do /users/1, użytkownik 1 jest ładowany i ustawiany na $scope.

Następnie, gdy nawiguję do /users/2, użytkownik 2 jest ładowany. Czy to samo wystąpienie zostało UserEditorCtrlponownie użyte, czy też zostało utworzone nowe wystąpienie?

  • Jeśli jest to nowa instancja, co powoduje zniszczenie pierwszej instancji?
  • Jeśli zostanie ponownie wykorzystany, jak to działa? (tzn. metoda ładowania danych wydaje się działać podczas tworzenia kontrolera)
Marty Pitt
źródło

Odpowiedzi:

227

Właściwie pytanie brzmi: jaki jest cykl życia ngViewkontrolera.

Kontrolery nie są singletonami. Każdy może utworzyć nowy kontroler i nigdy nie jest on automatycznie niszczony. Faktem jest, że zasadniczo jest on związany z cyklem życia jego podstawowego zakresu. Kontroler nie jest automatycznie niszczony za każdym razem, gdy niszczony jest jego zakres. Jednak po zniszczeniu bazowego zakresu jego kontroler jest bezużyteczny (przynajmniej z założenia powinien być).

Odpowiadając na konkretne pytanie, ngViewdyrektywa (tak samo jak ngControllerdyrektywa) zawsze tworzy nowy kontroler i nowy zakres za każdym razem, gdy nawigacja się dzieje. A ostatni zakres ma być zniszczony , jak również.

„Wydarzenia” cyklu życia są dość proste. Twoje „zdarzenie tworzenia” jest konstrukcją samego kontrolera. Po prostu uruchom swój kod. Aby wiedzieć, kiedy stanie się bezużyteczny ( „zdarzenie zniszczenia” ), posłuchaj $destroyzdarzenia zasięgu :

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

W ngViewszczególności możesz wiedzieć, kiedy treść zostanie załadowana przez zdarzenie scope $viewContentLoaded:

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

Oto Plunker z próbą koncepcyjną (otwórz okno konsoli).

Caio Cunha
źródło
10
Obecnie kod, który niszczy zakres $, znajduje się na stronie github.com/angular/angular.js/blob/… . Bardzo pomocne, dzięki!
w00t
4
viewContentLoaded działa tylko wtedy, gdy używasz limitu czasu, ponieważ jest on wywoływany tuż przed załadowaniem szablonu ... dokumenty mówią inaczej, ale odnoszą się do raw, template: "HTML STRING"gdy jest to plik szablonu, który jest ładowany asynchronicznie.
user3338098,