'this' vs $ scope w kontrolerach AngularJS
W sekcji "Utwórz komponenty" na stronie głównej AngularJS znajduje się przykład:
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);
}
}
Zwróć uwagę, jak Metoda select
jest dodawana do $scope
, ale metoda addPane
jest dodawana do this
. Jeśli zmienię go na $scope.addPane
, Kod się zepsuje.
Dokumentacja mówi, że w rzeczywistości istnieje różnica, ale nie wspomina, jaka jest różnica:
Poprzednie wersje Angular (pre 1.0 RC) pozwoliły używać
this
zamiennie z Metoda$scope
, ale tak już nie jest. Wewnątrz metod zdefiniowanych w zakresiethis
i$scope
są wymienne (zestawy kątowethis
do$scope
), ale nie wewnątrz twojego konstruktora kontrolera.
Jak działa this
i $scope
w kontrolerach AngularJS?
7 answers
"Jak działają
this
i$scope
w kontrolerach AngularJS?"
Krótka odpowiedź :
-
this
- gdy wywoływana jest funkcja konstruktora kontrolera,
this
jest kontrolerem. - gdy wywołana jest funkcja zdefiniowana na obiekcie
$scope
,this
jest "zakresem, w którym funkcja została wywołana". To może(lub nie!) be the$scope
that the function is defined on. Zatem wewnątrz funkcji,this
i$scope
mogą Nie bądź taki sam.
- gdy wywoływana jest funkcja konstruktora kontrolera,
-
$scope
- każdy kontroler ma powiązany obiekt
$scope
. - funkcja kontrolera (konstruktora) jest odpowiedzialna za ustawienie właściwości modelu i funkcji/zachowania na powiązanym z nim
$scope
. - tylko metody zdefiniowane na tym obiekcie
$scope
(i nadrzędne obiekty scope, jeśli w grze jest dziedziczenie prototypowe) są dostępne z widoku HTML/. Np. zng-click
, filtrów itp.
- każdy kontroler ma powiązany obiekt
Długie odpowiedź :
Funkcja kontrolera jest funkcją konstruktora JavaScript. Podczas wykonywania funkcji konstruktora (np. podczas ładowania widoku), this
(tzn. "kontekst funkcji") jest ustawiany na obiekt kontrolera. Tak więc w funkcji konstruktora kontrolera "tabs", gdy zostanie utworzona funkcja addPane
this.addPane = function(pane) { ... }
Jest tworzony na obiekcie kontrolera, a nie na $scope. Widoki nie mogą zobaczyć funkcji addPane -- mają dostęp tylko do funkcji zdefiniowanych w $scope. Innymi słowy, w HTML to nie zadziała:
<a ng-click="addPane(newPane)">won't work</a>
Po wykonaniu funkcji konstruktora kontrolera "tabs" mamy:
Przerywana czarna linia wskazuje dziedziczenie prototypowe-izolowany zakres prototypowo dziedziczy z Zakres . (Nie dziedziczy prototypowo z zakresu, w którym dyrektywa została napotkana w HTML.)
Teraz funkcja link dyrektywy pane chce komunikować się z dyrektywą tabs (co naprawdę oznacza, że musi w jakiś sposób wpłynąć na tabulatory isolate $scope). Zdarzenia mogą być użyte, ale innym mechanizmem jest posiadanie dyrektywy pane require
kontrolera tabs. (Wydaje się, że nie istnieje mechanizm dla dyrektywy pane do require
tabs $scope.)
Nasuwa się więc pytanie: jeśli mamy tylko dostęp do kontrolera tabs, to w jaki sposób uzyskamy dostęp do tabs isolate $scope (czego tak naprawdę chcemy)?
Czerwona kropkowana linia jest odpowiedzią. Na funkcja addPane ()" scope "(mam tu na myśli JavaScript ' s function scope/closures) daje funkcji dostęp do tabulatorów isolate $scope. To znaczy, addPane() ma dostęp do "tabs IsolateScope" na powyższym diagramie z powodu zamknięcia, które zostało utworzone podczas definiowania addPane (). (Gdybyśmy zamiast tego zdefiniowali addpane () w obiekcie tabs $scope, dyrektywa pane nie miałaby dostępu do tej funkcji, a zatem nie miałaby możliwości komunikowania się z tabs $scope.)
Aby odpowiedzieć druga część twojego pytania: how does $scope work in controllers?
:
W funkcjach zdefiniowanych na $scope, this
jest ustawione na "$scope w efekcie Gdzie / Kiedy funkcja została wywołana". Załóżmy, że mamy następujący kod 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>
I ParentCtrl
(wyłącznie) ma
$scope.logThisAndScope = function() {
console.log(this, $scope)
}
Kliknięcie pierwszego linku pokaże, że this
i $scope
są takie same, ponieważ "zakres obowiązujący, gdy funkcja została wywołana " jest zakresem skojarzonym z ParentCtrl
.
Kliknięcie drugiego linku ujawni this
i $scope
są , a nie tym samym, ponieważ "zakres obowiązujący, gdy funkcja została wywołana" jest zakresem związanym z ChildCtrl
. Więc tutaj {[4] } jest ustawione na ChildCtrl
' s $scope
. Wewnątrz metody, $scope
jest nadal $scope ParentCtrl
.
Staram się nie używać this
wewnątrz funkcji zdefiniowanej na $scope, ponieważ staje się to mylące, na który $scope ma wpływ, zwłaszcza biorąc pod uwagę, że ng-repeat, ng-include, ng-switch i dyrektywy wszyscy mogą tworzyć własne lunety dla dzieci.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-01 10:32:30
Powodem przypisania do tego "addPane" jest dyrektywa <pane>
.
Dyrektywa pane
robi require: '^tabs'
, która umieszcza kontroler tabs z nadrzędnej dyrektywy, w funkcji link.
addPane
jest przypisany do this
tak, że funkcja link pane
może go zobaczyć. Następnie w funkcji pane
link, addPane
jest tylko właściwością kontrolera tabs
i jest to tylko tabsControllerObject.addPane. Tak więc funkcja łączenia dyrektywy pane może uzyskać dostęp do kontrolera tabulatorów obiekt i tym samym dostęp do metody addPane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-10 09:11:52
Właśnie przeczytałem dość ciekawe Wyjaśnienie na temat różnicy między nimi i rosnącą preferencją dołączania modeli do kontrolera i aliasów kontrolera, aby powiązać modele z widokiem. http://toddmotto.com/digging-into-angulars-controller-as-syntax / to artykuł.
Nie wspomina o tym, ale definiując dyrektywy, jeśli chcesz podzielić coś między wieloma dyrektywami i nie chcesz mieć Usługi (istnieją uzasadnione przypadki, w których usługi są kłopotliwe), Dołącz dane do kontrolera dyrektywy nadrzędnej.Uwaga: oryginalny link nadal istnieje, ale zmiany w formatowaniu sprawiły, że trudno go odczytać. Łatwiej jest wyświetlić w oryginale .
Usługa $scope
zapewnia wiele przydatnych rzeczy, $watch
jest najbardziej oczywistą, ale jeśli wszystko, czego potrzebujesz, aby powiązać dane z widokiem, użycie zwykłego kontrolera i 'kontrolera as' w szablonie jest w porządku i prawdopodobnie preferowane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-19 16:57:53
Polecam przeczytać poniższy post: AngularJS: "Controller as" czy "$ scope"?
Opisuje bardzo dobrze zalety używania " Controller as "do wystawiania zmiennych nad"$scope".
Wiem, że pytałeś konkretnie o metody, a nie zmienne, ale myślę, że lepiej trzymać się jednej techniki i być z nią spójnym.
Więc moim zdaniem, ze względu na problem zmiennych omówiony w poście, lepiej po prostu użyć " kontrolera jako" techniki, a także zastosować ją do metod.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-23 09:29:25
W tym kursie ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) wyjaśniają, jak używać "tego" i wielu innych rzeczy.
Jeśli dodajesz metodę do kontrolera za pomocą metody "this", musisz ją wywołać w widoku z nazwą kontrolera" dot " swojej właściwości lub metody.
Na przykład używając kontrolera w widoku możesz mieć taki kod:
<div data-ng-controller="YourController as aliasOfYourController">
Your first pane is {{aliasOfYourController.panes[0]}}
</div>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-24 07:29:37
Poprzednie wersje Angular (pre 1.0 RC) pozwoliły na użycie tego zamiennie z metodą $ scope, ale nie jest to już case. Wewnątrz metod zdefiniowanych w zakresie this oraz $scope znajdują się wymienne (angular ustawia to na $scope), ale nie inaczej wewnątrz konstruktora kontrolera.
Aby przywrócić to zachowanie (czy ktoś wie dlaczego zostało zmienione?) można dodać:
return angular.extend($scope, this);
Na końcu funkcji kontrolera (pod warunkiem, że $scope został wstrzyknięty do tej funkcji kontrolera).
To ma przyjemny efekt posiadania dostępu do zakresu nadrzędnego poprzez obiekt kontrolera, który można uzyskać w potomku za pomocą require: '^myParentDirective'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-20 08:46:34
$ scope ma inne 'this' niż kontroler 'this'.Tak więc, jeśli umieścisz konsolę.log (this) wewnątrz kontrolera daje obiekt (controller) i to.addPane () dodaje metodę addPane do obiektu kontrolera. Ale $scope ma inny zakres i wszystkie metody w jego zakresie muszą być dostępne przez $scope.methodName ().
this.methodName()
wewnątrz kontrolera oznacza dodanie methos wewnątrz obiektu kontrolera.$scope.functionName()
jest w HTML i wewnątrz
$scope.functionName(){
this.name="Name";
//or
$scope.myname="myname"//are same}
Wklej ten kod w edytorze i otwórz konsolę, aby widzisz...
<!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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-07 09:06:17