2016-04-15 18 views
0

Ich bin mit einem sehr seltsamen Problem mit Variablen in einem Controller von einem anderen Controller entführt. Hier sind die Details:angularjs: Controller Hijacking eine andere Controller-Variable

In meinem HTML habe ich zwei ng-View-Tags. Jedes Tag führt zu einem TemplateURL (einem HTML), das seinen eigenen entsprechenden Controller hat. Ctrl1 und Ctrl2

die beiden ng-Ansichten sind auf der gleichen Ebene in der HTML-Hierarchie - das heißt, man ist nicht das Kind eines anderen

Controller1 sieht wie folgt aus:

ngEpMod.controller('Ctrl1',[function() { 

    selfX = this; 

    abc = 'abc controller1'; 
    console.log(abc); // break point 1 

    selfX.query = function() { 
     console.log("abc="); 
     console.log(abc); // break point 2 
     console.log("search query="); 
     console.log(selfX.searchQ); 
     lySP.searchHomes(); 

    }; 

}]); 

Controller2 Aussehen wie folgt:

Beide Controller sind im HTML-Code mit einer "Controller as" -Syntax verknüpft.

Die Abfrage() -Methode in Ctrl1 wird ausgelöst, wenn Benutzer Benutzer auf eine Schaltfläche klickt (ng-Klick)

Mystery: Als ich die HTML-Seite ($ state) laden, die die beiden ng-Ansichten hat, wie ich bin Beobachtung der Browser-Konsole. Ich bemerke, dass der abc-Wert in break-point1 "abc controller1" ist, aber wenn die query() -Methode ausgelöst wird, ändert sie sich mysteriös in "abc controller2". Es gibt keine globale Variable mit diesem Namen! Wie ich es verstehe, wird beim Anlegen der Seite zuerst Ctrl1 erzeugt, also an Breakpoint 1 hat abc den richtigen Wert, dann wird Ctrl2 erzeugt und irgendwie high-bucht die abc-Variable! Fremder ist sogar, dass ich dieses Problem zuerst mit meiner Selbstvariable bemerkte (self = das) und dann führte ich abc nur für zusätzliche Überprüfung ein

Gurus, ich bin ein Neuling und würde Ihre Hilfe wirklich schätzen.

Antwort

0

durch eine Variable ohne var (oder let in ES6) zu schaffen, haben Sie eine globale Variable erstellt Fenster angehängt:

abc = 'abc controller1'; gleich zu window.abc = 'abc controller1';

Wenn der erste Controller instanziiert es die Variable abc erklärt auf Fenster. Wenn der 2. Controller instanziiert wird, ändert er den globalen Variableninhalt abc.

Um dies zu vermeiden, definieren Sie in diesem Fall var abc in beiden Controllern.

Um es in Zukunft zu vermeiden hinzufügen 'use strict'; Verzögerung für jede Funktion, zum Beispiel:

ngEpMod.controller('Ctrl2',[function() { 
    'use strict'; 

    self = this; 
    var abc = 'abc controller2'; 

}]); 

Strict-Modus wird Fehler auslösen, wenn Sie diesen Fehler machen (alle viele andere). Von MDN:

Erstens, strikte Modus macht es unmöglich, versehentlich globale Variablen zu erstellen. Bei normalem JavaScript wird eine Variable in einer Zuweisung falsch beschriftet erstellt eine neue Eigenschaft auf dem globalen Objekt und weiterhin " " arbeiten (obwohl zukünftige Fehler möglich ist: wahrscheinlich, in modernen JavaScript). Zuordnungen, die versehentlich globale Variablen statt throw im Strict-Modus schaffen würde:

+0

Danke Ori - Ich habe gerade var zu abc hinzugefügt und das hat funktioniert! Ich bin so ein Dummy - der Nachteil der Codierung ohne genügend JavaScript-Kenntnisse. – hpep

+0

Keine Sorge. Lesen Sie über ['use strict'] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Strict_mode) und verwenden Sie es. Es wird dir helfen, Fehler zu finden und dir beibringen, was du nicht tun sollst. Lesen Sie außerdem [Javascript die guten Teile] (http://bdcampbell.net/javascript/book/javascript_the_good_parts.pdf) Buch. –

0

Ich würde fallen den Code unten in Ihre App über dieser Instantiierung (die meisten modernen Browser sollten diese Syntax verstehen für das Debuggen). Rufen Sie window.trackCtrl in jedem Controller-Konstruktor auf, öffnen Sie dann die Konsole in chrome oder firefox und geben Sie printCtrls() ein, und Sie sollten einen Ausdruck erhalten, wenn sie in der Reihenfolge erstellt wurden.

window.trackCtrl = (name) => { 
    var newCtrl = {} 
    newCtrl.name = name + '_' + performance.now() 
    window.trackingCtrls = window.trackingCtrls || [] 
    window.trackingCtrls.push(newCtrl) 
} 

window.printCtrls =() => Array.isArray(window.trackCtrls) ? window.trackingCtrls.forEach(x => console.info(x)) : console.error('trackCtrls not defined') 

Diese Fehler wie die Controller immer geladen außerhalb der Reihenfolge oder doppelte Kopien des Codes oder Bibliotheken immer geladen auf der gleichen Seite finden. Performance API hilft viel in diesen Situationen =>https://developer.mozilla.org/en-US/docs/Web/API/Performance/now

+0

wird tun - danke Chamberlain – hpep