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!
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.
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.
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.
ng-ifs
prüfenng-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.)turbolinks
-gem aus Ihrer application.js
-Datei entfernen. Ich habe einen ganzen Tag damit verschwendet, das zu entdecken. Antwort gefunden hier .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.
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
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.
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.
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.
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
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!
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.
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.
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'
}
}
});
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
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
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.
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.
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?
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.
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.
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.