wake-up-neo.net

AngularJS bekämpfen, der Controller zweimal ausführt

Ich verstehe, dass AngularJS den Code zweimal durchläuft, manchmal sogar mehr, wie $watch -Ereignisse, ständige Überprüfung der Modellzustände usw.

Jedoch mein code:

function MyController($scope, User, local) {

var $scope.User = local.get(); // Get locally save user data

User.get({ id: $scope.User._id.$oid }, function(user) {
  $scope.User = new User(user);
  local.save($scope.User);
});

//...

Wird zweimal ausgeführt und fügt 2 Datensätze in meine Datenbank ein. Ich lerne natürlich immer noch, da ich meinen Kopf schon seit Ewigkeiten gegen den Kopf schlug!

519
Greg

Der App-Router hat die Navigation zu MyController wie folgt angegeben:

$routeProvider.when('/',
                   { templateUrl: 'pages/home.html',
                     controller: MyController });

Aber ich hatte auch dies in home.html:

<div data-ng-controller="MyController">

Dies verdaute den Controller zweimal. Durch das Entfernen des data-ng-controller-Attributs aus dem HTML-Code wurde das Problem behoben. Alternativ könnte die controller:-Eigenschaft aus der Routing-Direktive entfernt worden sein.

Dieses Problem tritt auch bei der Navigation mit Registerkarten auf. Beispielsweise könnte app.js Folgendes enthalten:

  .state('tab.reports', {
    url: '/reports',
    views: {
      'tab-reports': {
        templateUrl: 'templates/tab-reports.html',
        controller: 'ReportsCtrl'
      }
    }
  })

Die entsprechende HTML-Registerkarte für Berichte kann folgendermaßen aussehen:

<ion-view view-title="Reports">
  <ion-content ng-controller="ReportsCtrl">

Dies führt auch dazu, dass der Controller zweimal ausgeführt wird.

1030
Greg

AngularJS-Dokumente - ngController
Beachten Sie, dass Sie Controller auch an das DOM anschließen können, indem Sie es deklarieren in einer Streckendefinition über den Streckendienst $. Ein häufiger Fehler ist deklarieren Sie den Controller erneut mit ng-controller in der Vorlage selbst. Dadurch wird der Controller angeschlossen und ausgeführt zweimal.

Wenn Sie ngRoute mit der Direktive ng-view verwenden, wird der Controller standardmäßig mit diesem dom-Element verbunden (oder ui-view, wenn Sie einen ui-router verwenden). Sie müssen es also nicht erneut in der Vorlage anhängen.

124
shxfee

Ich habe das gerade durchgemacht, aber das Thema unterschied sich von der akzeptierten Antwort. Ich lasse das hier wirklich für mein zukünftiges Selbst, einschließlich der Schritte, die ich durchlaufen habe, um es zu beheben.

  1. Entfernen redundanter Controller-Deklarationen
  2. Nachlaufende Schrägstriche in Routen prüfen
  3. Auf ng-ifs prüfen
  4. Überprüfen Sie, ob ng-view-Aufrufe unnötig umbrochen wurden (Ich hatte versehentlich einen ng-view hinterlassen, der meinen tatsächlichen ng-view umhüllte. Dies führte zu drei Aufrufen an meine Controller.)
  5. Wenn Sie sich auf Rails befinden, sollten Sie den turbolinks-gem aus Ihrer application.js-Datei entfernen. Ich habe einen ganzen Tag damit verschwendet, das zu entdecken. Antwort gefunden hier .
  6. Initialisieren Sie die App zweimal mit ng-app und mit bootstrap. AngularJS wird zweimal gegen den Controller ausgeführt
  7. Bei der Verwendung von $ compile für das gesamte Element in der 'link'-Funktion der Direktive, für die auch ein eigener Controller definiert ist, werden Callbacks dieses Controllers in der Vorlage über ng-click usw. verwendet. Gefundene Antwort hier .
64
JesseBuesking

Ich möchte nur noch einen Fall hinzufügen, in dem der Controller zweimal initialisiert werden kann (dies ist tatsächlich für angle.js 1.3.1):

<div ng-if="loading">Loading...</div>
<div ng-if="!loading">
    <div ng-view></div>
</div>

In diesem Fall ist $ route.current bereits gesetzt, wenn ng-view initialisiert wird. Das verursacht doppelte Initialisierung.

Um dies zu beheben, ändern Sie einfach ng-if in ng-show/ng-hide und alles wird gut funktionieren.

12
DontRelaX

Möchte als Referenz hinzufügen:

Doppelte Controller-Code-Ausführung kann auch dadurch verursacht werden, dass der Controller in einer Direktive referenziert wird, die auch auf der Seite ausgeführt wird. 

z.B.

return {

            restrict: 'A',
            controller: 'myController',
            link: function ($scope) { ....

Wenn Sie auch ng-controller = "myController" in Ihrem HTML haben

7
gb2d

Bei der Verwendung von angle-ui-router mit Angular 1.3+ gab es ein Problem mit Render-Ansichten zweimal beim Routenübergang . Dies führte auch dazu, dass Controller zweimal ausgeführt wurden. Keine der vorgeschlagenen Lösungen funktionierte für mich.

Das Aktualisieren von angular-ui-router von 0.2.11 auf 0.2.13 löste jedoch ein Problem für mich.

7
fracz

Ich habe meine App und all ihre Abhängigkeiten in Stücke gerissen (Details hier: AngularJS App startet zweimal (versucht die üblichen Lösungen ..) )

Und am Ende war alles die Schuld des Batarang Chrome Plugins.

Auflösung in diese Antwort :

Ich würde nachdrücklich empfehlen, dass das erste, was auf der Liste steht, das Deaktivieren per Post ist, bevor der Code geändert wird. 

6
Lewis

Ich hatte das gleiche Problem, in einer einfachen App (ohne Routing und einer einfachen Ng-Controller-Referenz) und der Konstruktor meines Controllers wurde zweimal ausgeführt. Schließlich fand ich heraus, dass mein Problem die folgende Erklärung war, meine AngularJS-Anwendung in meiner Razor-Ansicht automatisch zu booten

<html ng-app="mTest1">

Ich habe es auch manuell mit winklig.bootstrap bootstrapping, d. H.

angular.bootstrap(document, [this.app.name]);

so einen von ihnen zu entfernen, funktionierte es für mich.

5
athina.bikaki

Wenn Sie wissen, dass Ihr Controller unbeabsichtigt mehr als einmal ausgeführt wird, suchen Sie in Ihren Dateien nach dem Namen des betreffenden Controllers, z. Wahrscheinlich wurde es in eine andere html/js-Datei kopiert und Sie haben vergessen, es zu ändern, wenn Sie diese Partials/Controller entwickeln oder verwenden. Quelle: Ich habe diesen Fehler gemacht

4
user3901016

In einigen Fällen wird Ihre Direktive zweimal ausgeführt, wenn Sie die Direktive nicht einfach wie folgt schließen:

<my-directive>Some content<my-directive>

Dadurch wird Ihre Direktive zweimal ausgeführt .. __ Es gibt auch einen anderen Fall, in dem Ihre Direktive zweimal ausgeführt wird:

stellen Sie sicher, dass Sie Ihre Direktive nicht zweimal in Ihren index.html aufnehmen!

4
pleerock

Das Problem, mit dem ich konfrontiert bin, ist vielleicht tangential, aber da Googeln mich zu dieser Frage brachte, könnte dies angemessen sein. Das Problem ist für mich unangenehm, wenn ich den UI-Router verwende, aber nur, wenn ich versuche, die Seite mit der Browser-Aktualisierungsschaltfläche zu aktualisieren. Die App verwendet den UI-Router mit einem übergeordneten abstrakten Status und den untergeordneten Status des übergeordneten Elements. In der App-Funktion run() gibt es den Befehl $state.go('...child-state...'). Der übergeordnete Zustand verwendet eine resolve, und ich dachte zunächst, dass ein untergeordneter Controller zweimal ausgeführt wird.

Alles ist in Ordnung, bevor der URL den Hash angehängt hat.
www.someoldwebaddress.org

Sobald die URL vom UI-Router geändert wurde,
www.someoldwebaddress.org#/childstate

... und dann, wenn ich Aktualisieren der Seite mit der Browser-Aktualisierungsschaltfläche, wird der $stateChangeStart zweimal ausgelöst und zeigt jeweils auf die childstate.

Die resolve im übergeordneten Status wird zweimal ausgelöst.

Vielleicht ist das ein kludge; dies scheint jedoch für mich das Problem zu beseitigen: Im Bereich des Codes, in dem $stateProvider zuerst aufgerufen wird, prüfen Sie mit first, ob window.location.hash eine leere Zeichenfolge ist . Wenn ja, ist alles gut; Wenn dies nicht der Fall ist, setzen Sie window.location.hash auf eine leere Zeichenfolge. Dann scheint der $state nur einmal und nicht zweimal zu gehen.

Wenn Sie sich nicht auf die Standardvariablen run und state.go(...) der App verlassen möchten, können Sie versuchen, den Hashwert zu erfassen und den Hashwert zu verwenden, um den untergeordneten Status zu bestimmen, den Sie sich vor der Seitenaktualisierung befanden, und einen Wert hinzuzufügen Bedingung für den Bereich in Ihrem Code, in dem Sie state.go(...) einstellen.

2
mg1075

Ich habe mir mit AngularJS 1.4 rc build den Kopf über dieses Problem gekratzt und dann festgestellt, dass keine der oben genannten Antworten zutreffend war, da sie zum Zeitpunkt der Veröffentlichung aus der neuen Router-Bibliothek für Angular 1.4 und Angular 2 stammte. Aus diesem Grund möchte ich hier eine Notiz für alle Benutzer ablegen, die möglicherweise die neue Angular-Routenbibliothek verwenden.

Wenn eine HTML-Seite eine ng-viewport-Direktive zum Laden von Teilen Ihrer App enthält, würde ein Klick auf einen in ng-link angegebenen Hyperlink dazu führen, dass der Ziel-Controller der zugehörigen Komponente zweimal geladen wird. Der geringfügige Unterschied besteht darin, dass der Controller nur einmal aufgerufen wird, wenn der Browser den Zielcontroller bereits geladen hat. 

Es wurde noch kein praktikabler Workaround gefunden, obwohl dieses Verhalten meiner Meinung nach mit der von shaunxu gemachten Beobachtung übereinstimmt, und hoffentlich würde dieses Problem beim zukünftigen Erstellen einer neuen Routenbibliothek und zusammen mit AngularJS 1.4-Releases behoben werden. 

2
codeful.element

In meinem Fall habe ich zwei Ansichten mit demselben Controller gefunden.

$stateProvider.state('app', {
  url: '',
  views: {
    "[email protected]": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/one.tpl.html'
    },
    "[email protected]": {
      controller: 'CtrlOne as CtrlOne',
      templateUrl: 'main/two.tpl.html'
    }
  }
});
2
Luke Eller

Diese doppelte Initialisierung ist aus einem anderen Grund passiert. Bei einigen Routenübergängen in meiner Anwendung wollte ich das Scrollen nahe an den oberen Rand der Seite erzwingen (z. B. in paginierten Suchergebnissen ... Wenn Sie auf Weiter klicken, gelangen Sie zum Anfang von Seite 2).

Ich tat dies, indem ich dem $rootScope$on$viewContentLoaded einen Listener hinzufügte, der (basierend auf bestimmten Bedingungen) ausgeführt wurde

$location.hash('top');

Unbeabsichtigterweise wurden meine Routen neu bewertet und die Controller neu initialisiert

1
Harry Lime

Mein Problem bestand darin, die Suchparameter wie folgt zu aktualisieren: $location.search('param', key);

sie können hier mehr darüber lesen

Controller wird zweimal aufgerufen, weil Parameter in der URL angehängt wurden

1
Gal Bracha

In meinem Fall lag es an dem von mir verwendeten URL-Muster

meine URL war wie/ui/project /: parameter1 /: parameter2. 

Paramerter2 brauchte ich nicht in allen Fällen des Zustandswechsels. In Fällen, in denen ich den zweiten Parameter nicht benötigte, wäre meine URL wie/ui/project /: parameter1 /. Wenn ich also eine Statusänderung hatte, werde ich meinen Controller zweimal aktualisieren lassen.

Die Lösung bestand darin, Parameter2 als leere Zeichenfolge festzulegen und die Statusänderung vorzunehmen.

1
Sherin Syriac

In meinem Fall löste das Umbenennen des Controllers in einen anderen Namen das Problem.

Es gab einenKonflikt der Controller-Namen mit dem Modul "angle-ui-tree": Ich habe meinen Controller von "CatalogerTreeController" in "TreeController" umbenannt und dieser Controller wird zweimal gestartet auf der Seite, in der die Anweisung "ui-tree" verwendet wird, da diese Anweisung einen Controller mit dem Namen "TreeController" verwendet.

1
AlexDEV.pro

Ich hatte das gleiche Problem und nachdem ich alle Antworten ausprobiert hatte, stellte ich schließlich fest, dass ich aus meiner Sicht eine Anweisung hatte, die an denselben Controller gebunden war.

APP.directive('MyDirective', function() {
  return {
    restrict: 'AE',
    scope: {},
    templateUrl: '../views/quiz.html',
    controller: 'ShowClassController'
}
});

Nach dem Entfernen der Anweisung wurde der Controller nicht mehr zweimal aufgerufen. Jetzt ist meine Frage, wie kann diese Direktive ohne dieses Problem an den Controller-Bereich gebunden werden?

0

Ich habe gerade meine gelöst, was eigentlich ziemlich enttäuschend war. Es ist eine ionische Hybrid-App, ich habe ui-router v0.2.13 verwendet. In meinem Fall gibt es einen epub-Leser (mit epub.js), der fortlaufend "kein Dokument gefunden" meldete, sobald ich zu meiner Buchbibliothek navigiere und ein anderes Buch auswähle. Beim Neuladen wurde das Browser-Buch einwandfrei gerendert, aber als ich ein anderes Buch auswählte, kam das gleiche Problem wieder.

Meine Lösung war sehr einfach. Ich habe gerade reload:true von $state.go("app.reader", { fileName: fn, reload: true }); in meiner LibraryController entfernt.

0
maksbd19

Ich habe das gleiche Problem in [email protected], und da der extra Schrägstrich am Ende der Regex-Route liegt:

.when('/goods/publish/:classId/', option)

zu

.when('/goods/publish/:classId', option)

und es funktioniert richtig.

0
B.Ma

Für diejenigen, die die ControllerAs-Syntax verwenden, geben Sie die Controller-Bezeichnung im $ routeprovider wie folgt an:

$routeprovider
        .when('/link', {
            templateUrl: 'templateUrl',
            controller: 'UploadsController as ctrl'
        })

oder

$routeprovider
        .when('/link', {
            templateUrl: 'templateUrl',
            controller: 'UploadsController'
            controllerAs: 'ctrl'
        })

Wenn Sie den $ routeprovider deklariert haben, geben Sie den Controller nicht wie in der Ansicht an. Verwenden Sie stattdessen das Etikett in der Ansicht.

0
M. Arnold