Im Bereich "Komponenten erstellen" auf der Homepage von AngularJS gibt es folgendes Beispiel:
controller: function($scope, $element) {
var panes = $scope.panes = [];
$scope.select = function(pane) {
angular.forEach(panes, function(pane) {
pane.selected = false;
});
pane.selected = true;
}
this.addPane = function(pane) {
if (panes.length == 0) $scope.select(pane);
panes.Push(pane);
}
}
Beachten Sie, wie die select
-Methode zu $scope
hinzugefügt wird, die addPane
-Methode jedoch zu this
. Wenn ich es in $scope.addPane
ändere, bricht der Code.
Die Dokumentation sagt, dass es tatsächlich einen Unterschied gibt, aber es wird nicht erwähnt, was der Unterschied ist:
In früheren Versionen von Angular (vor 1.0 RC) konnten Sie
this
austauschbar mit der$scope
-Methode verwenden. Dies ist jedoch nicht mehr der Fall. Innerhalb von Methoden, die im Gültigkeitsbereichthis
und$scope
definiert sind, sind austauschbar (Winkelsätzethis
bis$scope
), ansonsten jedoch nicht in Ihrem Controller-Konstruktor.
Wie funktionieren this
und $scope
in AngularJS-Controllern?
"Wie funktionieren
this
und$scope
in AngularJS-Controllern?"
Kurze Antwort:
this
this
der Controller.$scope
-Objekt definierte Funktion aufgerufen wird, ist this
der "Gültigkeitsbereich, in dem die Funktion aufgerufen wurde". Dies kann (oder auch nicht!) Der $scope
sein, für den die Funktion definiert ist. Innerhalb der Funktion können this
und $scope
not nicht gleich sein.$scope
$scope
-Objekt zugeordnet.$scope
verantwortlich.$scope
-Objekt definierte Methoden (und übergeordnete Bereichsobjekte, wenn prototypische Vererbung im Spiel ist) sind über die HTML-Ansicht/view verfügbar. Zum Beispiel von ng-click
, Filter usw.Lange Antwort:
Eine Controller-Funktion ist eine JavaScript-Konstruktorfunktion. Wenn die Konstruktorfunktion ausgeführt wird (z. B. wenn eine Ansicht geladen wird), wird this
(d. H. Der "Funktionskontext") auf das Steuerungsobjekt gesetzt. Also in der Controller-Konstruktorfunktion "tabs", wenn die addPane-Funktion erstellt wird
this.addPane = function(pane) { ... }
es wird für das Controller-Objekt erstellt, nicht für $ scope. Ansichten können die addPane-Funktion nicht sehen - sie haben nur Zugriff auf Funktionen, die in $ scope definiert sind. Mit anderen Worten, im HTML funktioniert das nicht:
<a ng-click="addPane(newPane)">won't work</a>
Nachdem die Controller-Konstruktorfunktion "tabs" ausgeführt wurde, haben wir Folgendes:
Die gestrichelte schwarze Linie zeigt die prototypische Vererbung an - ein Isolatumfang, der prototypisch von/- Scope erbt. (Es erbt nicht prototypisch den Gültigkeitsbereich, in dem die Direktive im HTML gefunden wurde.)
Nun möchte die Link-Funktion der Bereichs-Direktive mit der Tabs-Direktive kommunizieren (was wirklich bedeutet, dass sie die Tabulatoren beeinflussen muss, die $ scope auf irgendeine Weise isolieren). Ereignisse könnten verwendet werden, aber ein anderer Mechanismus besteht darin, dass die Bereichsanweisung require
den Registerkarten-Controller hat. (Es scheint keinen Mechanismus für die Bereichsrichtlinie zu geben, mit der require
die Registerkarten $ Gültigkeitsbereich sind.)
Das wirft also die Frage auf: Wenn wir nur Zugriff auf den Tabs-Controller haben, wie können wir dann auf die Tabs zugreifen, die $ scope (was ist das, was wir wirklich wollen) haben?
Nun, die rote gepunktete Linie ist die Antwort. Der Funktionsumfang der Funktion addPane () (ich beziehe mich hier auf die Funktionsumfang/Schließungen von JavaScript) gibt der Funktion Zugriff auf die Tabs isolate $ scope. Das heißt, addPane () hat Zugriff auf die "Registerkarten IsolateScope" im obigen Diagramm, da bei der Definition von addPane () ein Abschluss erstellt wurde. (Wenn wir stattdessen addPane () für das $ scope -Objekt der Tabs definiert hätten, hätte die pane Direktive keinen Zugriff auf diese Funktion, und daher hätte sie keine Möglichkeit, mit den $ tabs der Tabs zu kommunizieren.)
Um den anderen Teil Ihrer Frage zu beantworten: how does $scope work in controllers?
:
Innerhalb von Funktionen, die für $ scope definiert sind, ist this
auf "den Gültigkeitsbereich von $ scope wo/wann die Funktion aufgerufen wurde" festgelegt. Nehmen wir an, wir haben folgendes HTML:
<div ng-controller="ParentCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope
<div ng-controller="ChildCtrl">
<a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope
</div>
</div>
Und die ParentCtrl
(nur) hat
$scope.logThisAndScope = function() {
console.log(this, $scope)
}
Wenn Sie auf den ersten Link klicken, wird angezeigt, dass this
und $scope
gleich sind, da "der Gültigkeitsbereich, in dem die Funktion aufgerufen wurde" der der ParentCtrl
-Gültigkeitsbereich zugeordnete Bereich ist.
Wenn Sie auf den zweiten Link klicken, werden this
und $scope
nicht gleich, da "der Gültigkeitsbereich beim Aufruf der Funktion" der der ChildCtrl
zugewiesene Gültigkeitsbereich ist. Hier ist also this
auf ChildCtrl
s $scope
gesetzt. Innerhalb der Methode ist $scope
immer noch der $ -Bereich von ParentCtrl
.
Ich versuche, this
nicht innerhalb einer Funktion zu verwenden, die für $ scope definiert ist, da es verwirrend wird, welcher $ scope betroffen ist, vor allem wenn man bedenkt, dass ng-repeat, ng-include, ng-switch und Direktiven alle ihre eigenen untergeordneten Bereiche erstellen können .
Der Grund für 'addPane' ist auf die <pane>
-Direktive zurückzuführen.
Die pane
-Direktive macht require: '^tabs'
, wodurch das Controller-Objekt der Registerkarten aus einer übergeordneten Direktive in die Link-Funktion eingefügt wird.
addPane
ist this
zugewiesen, damit die pane
link-Funktion sie sehen kann. In der pane
link-Funktion ist addPane
nur eine Eigenschaft des tabs
-Controllers und nur tabsControllerObject.addPane. Die Verknüpfungsfunktion der Bereichsanweisung kann also auf das Controller-Objekt der Registerkarten und somit auf die addPane-Methode zugreifen.
Ich hoffe, meine Erklärung ist klar genug. Es ist schwer zu erklären.
Ich habe gerade eine ziemlich interessante Erklärung über den Unterschied zwischen den beiden gelesen und eine wachsende Vorliebe, Modelle an den Controller anzuschließen und den Controller als Alias zu bezeichnen, um Modelle an die Ansicht zu binden. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ ist der Artikel. Er erwähnt es nicht, aber wenn Sie Richtlinien definieren, müssen Sie die Daten an den Controller der übergeordneten Direktive anhängen, wenn Sie etwas für mehrere Anweisungen freigeben möchten und keinen Dienst wünschen (es gibt legitime Fälle, in denen Dienste unangenehm sind). Der $ scope-Dienst bietet viele nützliche Dinge, wobei $ watch das offensichtlichste ist. Wenn Sie jedoch nur Daten an die Ansicht binden müssen, ist die Verwendung des einfachen Controllers und des Controllers in der Vorlage in Ordnung und möglicherweise vorzuziehen.
Ich empfehle Ihnen, den folgenden Beitrag zu lesen: AngularJS: "Controller as" oder "$ scope"?
Es beschreibt sehr gut die Vorteile der Verwendung von "Controller as", um Variablen über "$ scope" bereitzustellen.
Ich weiß, dass Sie speziell nach Methoden und nicht nach Variablen gefragt haben, aber ich denke, dass es besser ist, sich an eine Technik zu halten und konsistent zu sein.
Meiner Meinung nach ist es wegen des in der Post diskutierten Variablenproblems besser, die "Controller as" -Technik zu verwenden und sie auch auf die Methoden anzuwenden.
In diesem Kurs ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) wird erklärt, wie man "this" und viele andere Dinge verwendet.
Wenn Sie dem Controller über diese Methode eine Methode hinzufügen, müssen Sie diese in der Ansicht mit dem Namen des Controllers "dot" Ihrer Eigenschaft oder Methode aufrufen.
Wenn Sie beispielsweise Ihren Controller in der Ansicht verwenden, haben Sie möglicherweise folgenden Code:
<div data-ng-controller="YourController as aliasOfYourController">
Your first pane is {{aliasOfYourController.panes[0]}}
</div>
In früheren Versionen von Angular (vor 1.0 RC) konnten Sie diese .__ verwenden. austauschbar mit der $ scope-Methode, aber dies ist nicht mehr die Fall. Innerhalb der im Geltungsbereich definierten Methoden sind dies und $ austauschbar (Winkel setzt dies auf $ scope), aber sonst nicht in Ihrem Controller-Konstruktor.
Um dieses Verhalten wieder herzustellen (weiß jemand, warum es geändert wurde?), Können Sie Folgendes hinzufügen:
return angular.extend($scope, this);
am Ende Ihrer Controller-Funktion (vorausgesetzt, dass $ scope in diese Controller-Funktion eingefügt wurde).
Dies hat eine gute Wirkung, wenn Sie über ein Controller-Objekt auf den übergeordneten Bereich zugreifen können, das Sie mit require: '^myParentDirective'
in das untergeordnete Objekt aufnehmen können.
$ scope hat ein anderes 'this' als der Controller 'this'. Wenn Sie also eine console.log (this) in den Controller einfügen, erhalten Sie ein Objekt (Controller) und this.addPane () fügt dem Controller-Objekt die addPane-Methode hinzu. $ Scope hat jedoch einen anderen Gültigkeitsbereich, und alle Methoden in seinem Gültigkeitsbereich müssen über $ scope.methodName () .this.methodName()
im Controller aufgerufen werden. Das bedeutet, Methos im Controller-Objekt hinzuzufügen .$scope.functionName()
ist in HTML und inside
$scope.functionName(){
this.name="Name";
//or
$scope.myname="myname"//are same}
Fügen Sie diesen Code in Ihren Editor ein und öffnen Sie die Konsole.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=Edge">
<title>this $sope vs controller</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
<script>
var app=angular.module("myApp",[]);
app.controller("ctrlExample",function($scope){
console.log("ctrl 'this'",this);
//this(object) of controller different then $scope
$scope.firstName="Andy";
$scope.lastName="Bot";
this.nickName="ABot";
this.controllerMethod=function(){
console.log("controllerMethod ",this);
}
$scope.show=function(){
console.log("$scope 'this",this);
//this of $scope
$scope.message="Welcome User";
}
});
</script>
</head>
<body ng-app="myApp" >
<div ng-controller="ctrlExample">
Comming From $SCOPE :{{firstName}}
<br><br>
Comming from $SCOPE:{{lastName}}
<br><br>
Should Come From Controller:{{nickName}}
<p>
Blank nickName is because nickName is attached to
'this' of controller.
</p>
<br><br>
<button ng-click="controllerMethod()">Controller Method</button>
<br><br>
<button ng-click="show()">Show</button>
<p>{{message}}</p>
</div>
</body>
</html>