W sekcji „Tworzenie komponentów” na stronie głównej AngularJS znajduje się ten 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ę, w jaki select
sposób metoda jest dodawana $scope
, ale addPane
metoda jest dodawana do this
. Jeśli zmienię to na $scope.addPane
, kod się psuje.
Dokumentacja mówi, że tak naprawdę jest różnica, ale nie wspomina o różnicy:
Poprzednie wersje Angulara (wcześniej 1.0 RC) pozwalały na używanie
this
zamiennie z tą$scope
metodą, ale już tak nie jest. Wewnątrz metod zdefiniowanych w zakresiethis
i$scope
są one wymienne (zestawy kątowethis
do$scope
), ale nie inaczej wewnątrz konstruktora kontrolera.
Jak działa this
i $scope
działa w kontrolerach AngularJS?
angularjs
angularjs-scope
this
Aleksiej Boronina
źródło
źródło
Odpowiedzi:
Krótka odpowiedź :
this
this
to kontroler.$scope
wywoływanathis
jest funkcja zdefiniowana w obiekcie, „zasięg obowiązuje, gdy funkcja została wywołana”. Może to być (lub nie!)$scope
Funkcja zdefiniowana na tej funkcji. Więc wewnątrz funkcjithis
i$scope
może nie być taka sama.$scope
$scope
obiekt.$scope
.$scope
obiekcie (i obiektach nadrzędnych, jeśli w grę wchodzi dziedziczenie prototypowe) są dostępne z widoku HTML /. Np. Zng-click
filtrów, itp.Długa odpowiedź :
Funkcja kontrolera to funkcja konstruktora JavaScript. Gdy funkcja konstruktora jest wykonywana (np. Gdy ładuje się widok),
this
(tzn. „Kontekst funkcji”) jest ustawiany na obiekt kontrolera. Tak więc w funkcji konstruktora kontrolera „tabs”, gdy tworzona jest funkcja addPanejest tworzony na obiekcie kontrolera, a nie na $ scope. Widoki nie widzą funkcji addPane - mają dostęp tylko do funkcji zdefiniowanych w $ scope. Innymi słowy, w HTML to nie zadziała:
Po wykonaniu funkcji konstruktora kontrolera „tabs” otrzymujemy:
Przerywana czarna linia wskazuje na dziedzictwo prototypowe - zakres izolowany prototypowo dziedziczy po Scope . (Nie dziedziczy prototypowo z zakresu obowiązującego w przypadku napotkania dyrektywy w HTML).
Teraz funkcja linkowania dyrektywy panelu chce komunikować się z dyrektywą tabs (co tak naprawdę oznacza, że musi wpływać na tabs w jakiś sposób izolować $ scope). Zdarzenia mogą być użyte, ale innym mechanizmem jest ustawienie dyrektywy
require
tabulatora na kontroler kart. (Wygląda na to, że nie ma mechanizmu dyrektywy panelurequire
w zakresie $ tabs.)Nasuwa się więc pytanie: jeśli mamy dostęp tylko do kontrolera kart, w jaki sposób uzyskujemy dostęp do kart izolujących $ scope (czego naprawdę chcemy)?
Cóż, czerwona kropkowana linia jest odpowiedzią. „Zasięg” funkcji addPane () (odnoszę się tutaj do zakresu / zamknięć funkcji JavaScript) daje tej funkcji dostęp do zakładek izolujących $ scope. Tj. AddPane () ma dostęp do „zakładek IsolateScope” na powyższym diagramie z powodu zamknięcia, które zostało utworzone, gdy zdefiniowano addPane (). (Jeśli zamiast tego zdefiniowaliśmy addPane () na 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ć na drugą część pytania
how does $scope work in controllers?
:W ramach funkcji zdefiniowanych w $ scope,
this
ustawiono na „zakres $, który obowiązuje gdzie / kiedy funkcja została wywołana”. Załóżmy, że mamy następujący kod HTML:I
ParentCtrl
(wyłącznie) maKliknięcie pierwszego linku pokaże to
this
i$scope
jest takie samo, ponieważ „ zakres obowiązujący w momencie wywołania funkcji ” to zakres powiązany zParentCtrl
.Kliknięcie drugiego linku ujawni
this
i$scope
to nie to samo, gdyż „ zakres w efekcie, gdy funkcja została wywołana ” jest zakres związany zChildCtrl
. Więc tutajthis
jest ustawiony naChildCtrl
„s$scope
. Wewnątrz metody$scope
nadalParentCtrl
znajduje się zakres $.Skrzypce
Staram się nie używać
this
wewnątrz funkcji zdefiniowanej w $ scope, ponieważ staje się mylące, którego $ zakres ma wpływ, szczególnie biorąc pod uwagę, że wszystkie powtórzenia, włączanie, przełączanie i przełączanie mogą tworzyć własne zakresy potomne.źródło
Powodem tego jest przypisanie „addPane” z powodu
<pane>
dyrektywy.pane
Dyrektywa robirequire: '^tabs'
, co stawia kontrolera wypustki obiekt z dyrektywy macierzystego do funkcji łącza.addPane
jest przypisany do,this
abypane
funkcja link mogła go zobaczyć. Następnie wpane
funkcji linkaddPane
jest tylko właściwościątabs
kontrolera i jest to po prostu tabsControllerObject.addPane. Tak więc funkcja łączenia dyrektywy panelu może uzyskać dostęp do obiektu kontrolera kart, a zatem uzyskać dostęp do metody addPane.Mam nadzieję, że moje wyjaśnienie jest wystarczająco jasne ... trudno to wyjaśnić.
źródło
Właśnie przeczytałem całkiem interesujące wyjaśnienie różnicy między nimi oraz rosnącą preferencję dołączania modeli do kontrolera i aliasu kontrolera w celu powiązania modeli z widokiem. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ to artykuł.
Nie wspomina o tym, ale jeśli definiujesz dyrektywy, jeśli musisz coś współdzielić między wieloma dyrektywami i nie chcesz usługi (istnieją uzasadnione przypadki, gdy usługi są kłopotliwe), to dołącz dane do kontrolera dyrektywy nadrzędnej.
$scope
Usługa zapewnia wiele przydatnych rzeczy,$watch
jest najbardziej oczywiste, ale jeśli wszystko czego potrzebujesz do danych wiążą się z widzenia, używając zwykłego kontrolera i „kontroler jako” w szablonie jest w porządku i bez wątpienia korzystne.źródło
Polecam przeczytać następujący post: AngularJS: „Controller as” lub „$ scope”?
Bardzo dobrze opisuje zalety używania „Controller as” do eksponowania zmiennych w stosunku do „$ scope”.
Wiem, że pytałeś konkretnie o metody, a nie zmienne, ale myślę, że lepiej trzymać się jednej techniki i być z nią zgodnym.
Tak więc, moim zdaniem, ze względu na problem zmiennych omawiany w poście, lepiej jest po prostu użyć techniki „Controller as” i zastosować ją również do metod.
źródło
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 dodasz metodę do kontrolera za pomocą „tej” metody, musisz wywołać ją w widoku z nazwą kontrolera „kropka” swoją właściwością lub metodą.
Na przykład używając kontrolera w widoku, możesz mieć taki kod:
źródło
$scope
, więc dziękuję za jego wzmiankę.as
athis
więc jak może pomóc wyjaśnić różnicę?$scope
nigdy nie wspomniano, nauczyłem się korzystać tylkothis
z kontrolerów. Problem polega na tym, że kiedy zaczynasz obsługiwać obietnice w swoim kontrolerze, masz wiele problemów z referencjamithis
i musisz zacząć robić takie rzeczy, jakvar me = this
odwoływanie się do modeluthis
z poziomu funkcji zwrotu obietnicy. Z tego powodu nadal jestem bardzo zdezorientowany, której metody powinienem użyć$scope
lubthis
.var me = this
albo.bind(this)
gdy robisz obietnice lub inne zamknięcia ciężkich rzeczy. Nie ma to nic wspólnego z Angularem.ng-controller="MyCtrl as MC"
jest to równoważne z umieszczeniem$scope.MC = this
samego kontrolera - definiuje instancję (this) MyCtrl w zakresie zastosowania w szablonie przez{{ MC.foo }}
Aby przywrócić to zachowanie (czy ktoś wie, dlaczego zostało zmienione?) Możesz dodać:
na końcu funkcji kontrolera (pod warunkiem, że do tej funkcji kontrolera został wprowadzony zakres $).
Daje to przyjemny efekt dostępu do zakresu nadrzędnego za pośrednictwem obiektu kontrolera, z którym można uzyskać dziecko
require: '^myParentDirective'
źródło
$ scope ma inne „to” niż kontroler „to”. Jeśli więc umieścisz console.log (this) w kontrolerze, otrzymasz obiekt (kontroler), a this.addPane () doda metodę AddPane do obiektu kontrolera. Ale zakres $ ma inny zakres i wszystkie metody w jego zakresie muszą być dostępne za pomocą $ scope.methodName ().
this.methodName()
wewnątrz kontrolera oznacza dodanie metosu do obiektu kontrolera.$scope.functionName()
jest w HTML i wewnątrzWklej ten kod w edytorze i otwórz konsolę, aby zobaczyć ...
źródło