Czy powinienem używać „this” czy „$ scope”?

251

Istnieją dwa wzorce dostępu do funkcji kontrolera: thisi $scope.

Którego należy użyć i kiedy? Rozumiem, że thisjest ustawiony na kontroler i $scopejest obiektem w łańcuchu zasięgu dla widoków. Ale dzięki nowej składni „Controller as Var” możesz z łatwością używać obu. Pytam więc, co jest najlepsze i jaki jest kierunek na przyszłość?

Przykład:

  1. Za pomocą this

    function UserCtrl() {
      this.bye = function() { alert('....'); };
    }
    
    <body ng-controller='UserCtrl as uCtrl'>
      <button ng-click='uCtrl.bye()'>bye</button>
    
  2. Za pomocą $scope

    function UserCtrl($scope) {
        $scope.bye = function () { alert('....'); };
    }
    
    <body ng-controller='UserCtrl'>
        <button ng-click='bye()'>bye</button>
    

Osobiście uważam, że this.namejest łatwiejsza dla oka i bardziej naturalna w porównaniu do innych wzorców OO Javascript.

Porada proszę?

SenseDeep
źródło
Używanie „tego” wydaje się nowe od Google I / O 2013 m.youtube.com/watch?v=HCR7i5F5L8c Również sprawdź tę odpowiedź: stackoverflow.com/questions/11605917/…
AlanW
Czy składnia „UserCtrl as uCtrl” jest nowa? Nie widzę tego udokumentowanego na stronach 1.0.6 lub 1.1.4 ngController.
Mark Rajcok
Okej, jest to udokumentowane na nowej stronie 1.1.5 ngController .
Mark Rajcok
1
Najlepsze wyjaśnienia dla $ scope i tego codetunnel.io/angularjs-controller-as-or-scope
Sai

Odpowiedzi:

229

Oba mają swoje zastosowania. Po pierwsze, trochę historii ...

$ scope jest „klasyczną” techniką, podczas gdy „kontroler jako” jest znacznie nowszy (od wersji 1.2.0 oficjalnie, chociaż wcześniej pojawiał się w niestabilnych wersjach wstępnych).

Oba działają idealnie dobrze, a jedyną złą odpowiedzią jest mieszanie ich w tej samej aplikacji bez wyraźnego powodu. Szczerze mówiąc, mieszanie ich będzie działać, ale tylko zwiększy zamieszanie. Więc wybierz jeden i rzuć nim. Najważniejsze jest zachowanie spójności.

Który? To zależy od Ciebie. Istnieje wiele innych przykładów $ scope, ale „kontroler jako” również zbiera parę. Czy jedno jest lepsze od drugiego? To jest dyskusyjne. Jak więc wybierasz?

Komfort

Wolę „kontroler jako”, ponieważ lubię ukrywać zakres $ i wystawiać członków z kontrolera na widok za pośrednictwem obiektu pośredniego. Ustawiając to. *, Mogę ujawnić tylko to, co chcę pokazać ze sterownika do widoku. Możesz to zrobić również za pomocą $ scope, po prostu wolę używać do tego standardowego JavaScript. W rzeczywistości koduję to w ten sposób:

var vm = this;

vm.title = 'some title';
vm.saveData = function(){ ... } ;

return vm;

Wydaje mi się to czystsze i ułatwia zobaczenie, co jest wystawiane na widok. Zauważ, że nazywam zmienną, którą zwracam, „vm”, co oznacza viewmodel. To tylko moja konwencja.

Z $ scope mogę robić te same rzeczy, więc nie dodawam ani nie umniejszam techniki.

$scope.title = 'some title';
$scope.saveData = function() { ... };

To zależy od ciebie.

Iniekcja

Z $ scope muszę wprowadzić $ scope do kontrolera. Nie muszę tego robić z kontrolerem, chyba że potrzebuję go z innego powodu (np. $ Broadcast lub zegarki, chociaż staram się unikać zegarków w kontrolerze).

AKTUALIZACJA Napisałem ten post o 2 opcjach: http://www.johnpapa.net/do-you-like-your-angular-controllers-with-or-without-sugar/

John Papa
źródło
4
Osobiście śledzę również twoje podejście za pomocą vm. Jedyny zapach, który wyczułam, to to, kiedy potrzebujesz konkretnie wchodzić w interakcje z $ scope, np. Subskrybować lub transmitować zdarzenia, uzyskiwać dostęp do zmiennych sprawdzania poprawności formularza w kontrolerze itp. To prowadzi do nieco mieszanego środowiska, w którym wciąż musisz wstrzyknąć $ scope nawet jeśli używasz kontrolera jako funkcji.
Beyers,
9
Dobrze. W tym przypadku nadal używany jest zakres $, ale jest on wykorzystywany raczej jako usługa. Kiedy wstrzykujemy usługi kątowe ($ scope, $ q itp.), Zapewniają one potrzebną funkcję. $ scope pozwala nam oglądać, aplikować, używać wiadomości oraz wiązania danych. I nawet jeśli używasz kontrolera jako, $ scope jest nadal używany, jest on po prostu streszczony
John Papa,
1
var vm = this;czy w widoku musisz też nazwać to „vm”? „kontroler jako vm”. Czy muszą być takie same?
Javid
2
@JohnPapa - Dlaczego szablony SideWaffle „nie zwracają vm;” podczas korzystania z kontrolera jako?
Kevin
2
Kontrolery @Kevin skutecznie działają jako Ctor i tym samym zwracają „to” już.
John Papa,
68

$scopejest usuwany w Angular 2.0. W związku z tym używanie thisbyłoby podejściem, które inni chcieliby zastosować , gdy zbliża się data wydania Angulara 2.0.

jason328
źródło
40

Moim zdaniem „to” w javascript ma wystarczająco dużo problemów, a dodanie do niego innego znaczenia / zastosowania nie jest dobrym pomysłem.

Dla jasności użyłbym $ scope.

AKTUALIZACJA

Omówiono tutaj składnię „kontrolera jako” . Nie jestem fanem, ale teraz, gdy jest to bardziej „oficjalny” konstrukt AngularJS, zasługuje na trochę uwagi.

Roy Truelove
źródło
10
Myślę, że najpierw musimy zrozumieć nową składnię „UserCtrl as uCtrl”, zanim będziemy mogli powiedzieć, która naszym zdaniem jest lepsza.
Mark Rajcok
Re „UserCtrl as uCtrl”, zgadzam się, należy to zrozumieć. Myślę, że to zły pomysł, z tych samych powodów, co przedstawione tutaj argumenty: groups.google.com/forum/#!topic/angular/84selECbp1I
Roy Truelove
4
Jeśli znasz Joom w JS , ma to sens. Kontroler jest klasą, a angular używa nowego operatora za każdym razem, gdy kontroler jest tworzony. Możesz go nie lubić, ale stwierdzenie, że istnieją problemy z używaniem „tego”, jest mylące. Jest to dopuszczalny przypadek użycia „tego”.
MJ
$ scope nie dodaje nic do przejrzystości. W rzeczywistości może być bardzo trudno wiedzieć, co się dzieje w widoku, gdy używasz $ scope i masz zagnieżdżone zakresy. Kontroler jako składnia wraz z użyciem tego dodaje znacznie większej przejrzystości. W widoku jest jasne i jasne, z którego zakresu kontrolera pochodzi metoda lub właściwość.
ddelrio1986,
1
Zgadzam się z @ ddelrio1986. Właśnie miałem problem z kartami bootstrap i agularnymi przy użyciu var vm = $ scope. Karty mają swój zakres, więc nie możesz używać tego tak, jak można się spodziewać, ale przy var vm = this wszystko działa tak, jak powinno.
user441521,
11

Myślę, że Controller As jest lepszy, ponieważ pozwala na łatwiejsze zagnieżdżanie zakresów, jak opisał Todd Motto tutaj:

http://toddmotto.com/digging-into-angulars-controller-as-syntax/

Zapewni to również, że zawsze masz co najmniej jeden. w twoim wiążącym wyrażeniu, które zmusza cię do podążania za poleceniem „ nie wiąż” z prymitywami .

Dodatkowo możesz odłączyć od zakresu, który odchodzi w wersji 2.0.

Ryan Vice
źródło
7

Dokumentacja Angulara wyraźnie mówi, że thiszalecane jest używanie . To, oprócz tego, że $scopejest usuwane, jest wystarczającym powodem, żebym nigdy tego nie używał $scope.

tjespe
źródło
4

„Zakres $ został usunięty w Angular 2.0” jason328 to dla mnie dobry powód. I znalazłem inny powód, aby pomóc mi dokonać wyboru: thisjest bardziej czytelny - kiedy widzę fooCtrl.barw HTML, od razu wiem, gdzie znaleźć definicję bar.

Aktualizacje: niedługo po przejściu na thisrozwiązanie zacząłem ominąć $scopesposób, który wymaga mniej pisania

ZZY
źródło
2

Wolę kombinację.

Pokaże to prosty console.log $ scope i „to” po zapełnieniu ich próbnymi danymi.

Zakres $ umożliwia dostęp do części kontrolera pod przykryciem, na przykład:

$$ChildScope: null;
$$childHead: null;
$$childTail: null;
$$listenerCount: Object;
$$listeners: Object;
$$nextSibling: Scope;
$$prevSibling: null;
$$watchers: null;
$$watcherCount: 0;
$id: 2;
$parent: Object;
foo: 'bar';

** Właściwości i metody z $$ nie są zalecane do manipulowania przez zespół Angular, ale $ może być bezpieczną grą do robienia fajnych rzeczy z $ parent i $ id.

„to” przechodzi od razu do sedna, łącząc dane i funkcje dwukierunkowe. Zobaczysz tylko to, co załączyłeś:

foo: 'bar';

Dlaczego więc wolę kombinację?

W aplikacjach zagnieżdżonych ui-router mogę uzyskać dostęp do głównego kontrolera, ustawić i wywołać uniwersalne wartości i funkcje w kontrolerze podrzędnym:

W głównym kontrolerze:

// Main Controller
var mainCtrl = this;
mainCtrl.foo = 'Parent at the bar';

W kontrolerze podrzędnym:

// Child Controller
var mainCtrl = $scope.$parent.mainCtrl;
var childCtrl = this;

// update the parent from within the child
childCtrl.underageDrinking = function(){
    mainCtrl.foo = 'Child at the bar';
}

// And then attach the child back to a property on the parent controller!
mainCtrl.currentCtrl = childCtrl;

Teraz możesz uzyskać dostęp do rodzica z poziomu dziecka i dziecka od rodzica!

Craig O. Curtis
źródło
1

Oba działają, ale jeśli zastosujesz rzeczy odpowiednie dla zakresu do $ scope, i jeśli zastosujesz rzeczy odpowiednie dla kontrolera do kontrolera, twój kod będzie łatwy do utrzymania. Ludziom, którzy mówią „Ugh, po prostu używaj zakresu, zapomnij o tym kontrolerze jako składni” ... To może działać tak samo, ale zastanawiam się, jak będziesz w stanie utrzymać ogromną aplikację bez utraty rzeczy.

Nick Manning
źródło