Was ist der Lebenszyklus eines AngularJS-Controllers?

199

Kann jemand bitte klären, wie der Lebenszyklus eines AngularJS-Controllers ist?

  • Ist ein Controller ein Singleton oder wird er bei Bedarf erstellt / zerstört?
  • Wenn letzteres der Fall ist, was löst die Erstellung / Zerstörung des Controllers aus?

Betrachten Sie das folgende Beispiel:

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

z.B:

Wenn ich im obigen Beispiel zu navigiere, /users/1wird Benutzer 1 geladen und auf gesetzt $scope.

Wenn ich dann zu navigiere, /users/2wird Benutzer 2 geladen. Wird dieselbe Instanz UserEditorCtrlwiederverwendet oder wird eine neue Instanz erstellt?

  • Wenn es sich um eine neue Instanz handelt, was löst die Zerstörung der ersten Instanz aus?
  • Wie funktioniert das, wenn es wiederverwendet wird? (dh die Methode zum Laden der Daten scheint beim Erstellen des Controllers ausgeführt zu werden)
Marty Pitt
quelle

Antworten:

227

Nun, eigentlich ist die Frage, wie der Lebenszyklus eines ngViewControllers ist.

Controller sind keine Singletons. Jeder kann einen neuen Controller erstellen und dieser wird niemals automatisch zerstört. Tatsache ist, dass es im Allgemeinen an den Lebenszyklus seines zugrunde liegenden Bereichs gebunden ist. Der Controller wird nicht automatisch zerstört, wenn sein Bereich zerstört wird. Nach der Zerstörung eines zugrunde liegenden Bereichs ist sein Controller jedoch unbrauchbar (zumindest sollte dies beabsichtigt sein).

Bei der Beantwortung Ihrer spezifischen Frage erstellt eine ngViewDirektive (auch für ngControllerDirektive) jedes Mal, wenn eine Navigation stattfindet , einen neuen Controller und einen neuen Bereich . Und das letzte Zielfernrohr wird ebenfalls zerstört .

Die Lebenszyklus- "Ereignisse" sind recht einfach. Ihr "Erstellungsereignis" ist die Konstruktion Ihres Controllers selbst. Führen Sie einfach Ihren Code aus. Um zu wissen, wann es unbrauchbar wird ( "Zerstörungsereignis" ), hören Sie sich das Bereichsereignis an $destroy:

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

Für ngViewInsbesondere sind Sie in der Lage zu wissen , wann der Inhalt durch den Bereich Ereignis geladen wird $viewContentLoaded:

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

Hier ist ein Plunker mit einem Konzeptnachweis (öffnen Sie Ihr Konsolenfenster).

Caio Cunha
quelle
10
Heutzutage befindet sich der Code, der den $ scope zerstört, unter github.com/angular/angular.js/blob/… . Sehr hilfreich, danke!
w00t
4
viewContentLoaded funktioniert nur, wenn Sie eine Zeitüberschreitung verwenden, da diese unmittelbar vor dem Laden der Vorlage ausgelöst wird. Die Dokumente sagen das Gegenteil, beziehen sich jedoch auf raw, template: "HTML STRING"wenn es sich um eine Vorlagendatei handelt, die asynchron geladen wird.
user3338098