Składnia AngularJs „kontroler jako” - wyjaśnienie?


121

Ja przeczytałem o nowej składni z angularjs dotyczącychcontroller as xxx

Składnia InvoiceController as invoicenakazuje Angularowi utworzenie wystąpienia kontrolera i zapisanie go w zmiennej faktury w bieżącym zakresie.

Wizualizacja:

wprowadź opis obrazu tutaj

Ok, więc nie będę miał parametru $scopew kontrolerze, a kod w kontrolerze będzie dużo czystszy.

Ale

Będę musiał określić inny alias w widoku

Więc do tej pory mogłem zrobić:

<input type="number" ng-model="qty"  />

....controller('InvoiceController', function($scope) {
   // do something with $scope.qty <--notice

A teraz mogę:

 <input type="number" ng-model="invoic.qty"  /> <-- notice 

  ....controller('InvoiceController', function() {
       // do something with  this.qty  <--notice

Pytanie

Jaki jest cel tego robić? usuwanie z jednego miejsca i dodawanie w innym miejscu?

Z przyjemnością zobaczę, czego mi brakuje.


8
Ten film bardzo dobrze to wyjaśnia. youtube.com/watch?v=tTihyXaz4Bo Myślę, że jest używany do czystszego kodu w HTML.
Fizer Khan

1
Przejrzystość. Nie przejmuję się używaniem $ scope.x Vs this.x w kontrolerze, ale moim zdaniem powiązanie z {{faktura.x}} mówi mi więcej niż tylko {{x}} (imho). Zastanawiam się również, czy to rozwiązuje problem, o którym słyszałem w kątowym, w którym nie-obiekty w kontrolerze mają problemy (więc things.x będzie w porządku, ale x spowoduje problem).
Matt Roberts

1
@MattRoberts, aby odnieść się do twojego ostatniego komentarza - problem niebędący przedmiotem, do którego się odnosisz, nie jest problemem kątowym, a raczej faktem dziedziczenia prototypowego języka JavaScript. Jest dobre wyjaśnienie, dlaczego dzieje się to w kątowym tutaj (wraz z tym, dlaczego controller asto naprawia).
Russ Matney

Jak zamienić $ scope. $ Broadcast? w tym nowym przypadku, ponieważ moja transmisja this. $ wydaje się nie działać
Gaurav

1
@Gaurav nadal możesz wstrzyknąć usługę $ scope do swojego kontrolera, nawet jeśli używasz kontrolera jako składni niektórych właściwości, metod itp.
Derek

Odpowiedzi:


163

Jest w tym kilka rzeczy.

Niektórzy ludzie nie lubią $scopeskładni (nie pytaj mnie dlaczego). Mówią, że mogliby po prostu użyć this. To był jeden z celów.

Wyjaśnienie, skąd pochodzi nieruchomość, też jest naprawdę przydatne.

Możesz zagnieżdżać kontrolery, a czytając kod HTML, jest całkiem jasne, gdzie znajduje się każda właściwość.

Możesz także uniknąć niektórych problemów z regułą kropki .

Na przykład mając dwa kontrolery, oba o tej samej nazwie `` nazwa '', możesz to zrobić:

<body ng-controller="ParentCtrl">
    <input ng-model="name" /> {{name}}

    <div ng-controller="ChildCtrl">
        <input ng-model="name" /> {{name}} - {{$parent.name}}
    </div>
</body>

Możesz modyfikować zarówno rodzica, jak i dziecko, nie ma problemu. Ale musisz użyć, $parentaby zobaczyć imię rodzica, ponieważ umieściłeś je w swoim kontrolerze podrzędnym. W ogromnym kodzie html $parentmoże być problem, nie wiesz, skąd pochodzi ta nazwa.

Dzięki temu controller asmożesz:

<body ng-controller="ParentCtrl as parent">
    <input ng-model="parent.name" /> {{parent.name}}

    <div ng-controller="ChildCtrl as child">
      <input ng-model="child.name" /> {{child.name}} - {{parent.name}}
    </div>
</body>

Ten sam przykład, ale jest o wiele jaśniejszy do odczytania.


10
Również tutaj jest całkiem dobry przykład, dlaczego to podejście może być dla niektórych mylące: stackoverflow.com/questions/25405543/…
Julian Hollmann

Jest to bardzo przydatne podczas zagnieżdżania kontrolerów!
C_J

1
Mam problem z podobną implementacją Twojej odpowiedzi, zobacz stackoverflow.com/questions/38315538
Cody

Pozwala to również na użycie klasy es6 jako kontrolera i odwoływanie się do metod w kodzie HTML. foo() { ... }jest o wiele czystszy niż $scope.foo = function() { ... }.
Brian McCutchon

17

Główną zaletą controller asskładni, którą widzę, jest to, że można pracować z kontrolerami jako klasami, a nie tylko z niektórymi funkcjami dekorującymi zakres, i korzystać z dziedziczenia. Często spotykam się z sytuacją, w której istnieje funkcjonalność bardzo podobna do wielu kontrolerów, a najbardziej oczywistą rzeczą jest utworzenie BaseControllerklasy i dziedziczenie po niej.

Mimo że istnieje dziedziczenie $ scope, które częściowo rozwiązuje ten problem, niektórzy ludzie wolą pisać kod w sposób bardziej OOP, co moim zdaniem ułatwia rozumowanie i testowanie kodu.

Oto skrzypce do zademonstrowania: http://jsfiddle.net/HB7LU/5796/


1
Powinno to uzyskać więcej głosów, ponieważ Skrzypce są naprawdę pomocne
Mawg mówi, że przywróć Monikę

13

Uważam, że jedna szczególna zaleta jest oczywista, gdy masz zagnieżdżone lunety. Teraz będzie całkowicie jasne, z jakiego zakresu pochodzi odwołanie do właściwości.


7

Źródło

Różnica między tworzeniem kontrolera przy użyciu $scope objecti przy użyciu “controller as”składni i maszyny wirtualnej

Tworzenie kontrolera przy użyciu obiektu $ scope

Zwykle tworzymy kontroler za pomocą obiektu $ scope, jak pokazano na poniższym liście:

myApp.controller("AddController", function ($scope) {



    $scope.number1;

    $scope.number2;

    $scope.result;

    $scope.add = function () {

        $scope.result = $scope.number1 + $scope.number2;

    }

});

Powyżej tworzymy AddController z trzema zmiennymi i jednym zachowaniem, używając kontrolera obiektu $ scope i widoku, które komunikują się ze sobą. Obiekt $ scope służy do przekazywania danych i zachowania do widoku. Skleja ze sobą widok i kontroler.

Zasadniczo obiekt $ scope wykonuje następujące zadania:

  1. Przekaż dane z kontrolera do widoku

  2. Przekaż zachowanie z kontrolera do widoku

  3. Skleja kontroler i widok razem

  4. Obiekt $ scope zostaje zmodyfikowany, gdy zmienia się widok, a widok zostaje zmodyfikowany, gdy właściwości obiektu $ scope ulegają zmianie

Dołączamy właściwości do obiektu $ scope, aby przekazać dane i zachowanie do widoku. Przed użyciem obiektu $ scope w kontrolerze, musimy przekazać go w funkcji kontrolera jako zależności.

Używanie składni „kontroler jako” i maszyny wirtualnej

Możemy przepisać powyższy kontroler, używając kontrolera jako składni i zmiennej vm, jak pokazano na poniższej liście:

myApp.controller("AddVMController", function () {

    var vm = this;

    vm.number1 = undefined;

    vm.number2=undefined;

    vm.result =undefined;

    vm.add = function () {

        vm.result = vm.number1 + vm.number2;

    }

});

Zasadniczo przypisujemy to do zmiennej vm, a następnie dołączamy do niej właściwość i zachowanie. W widoku możemy uzyskać dostęp do AddVmController używając kontrolera jako składni. Jest to pokazane na poniższej liście:

<div ng-controller="AddVMController as vm">

            <input ng-model="vm.number1" type="number" />

            <input ng-model="vm.number2" type="number" />

            <button class="btn btn-default" ng-click="vm.add()">Add</button>

            <h3>{{vm.result}}</h3>

  </div>

Oczywiście możemy użyć innej nazwy niż „vm” w kontrolerze jako składni. Pod maską AngularJS tworzy obiekt $ scope i dołącza właściwości oraz zachowanie. Jednak używając kontrolera jako składni, kod jest bardzo czysty na kontrolerze i tylko nazwa aliasu jest widoczna w widoku.

Oto kilka kroków, aby użyć kontrolera jako składni:

  1. Utwórz kontroler bez obiektu $ scope.

  2. Przypisz to do zmiennej lokalnej. Wolałem nazwę zmiennej jako vm, możesz wybrać dowolną nazwę.

  3. Dołącz dane i zachowanie do zmiennej maszyny wirtualnej.

  4. W widoku podaj alias kontrolerowi, używając kontrolera jako składni.

  5. Możesz nadać aliasowi dowolną nazwę. Wolę używać maszyny wirtualnej, chyba że nie pracuję z zagnieżdżonymi kontrolerami.

Przy tworzeniu kontrolera nie ma bezpośrednich zalet ani wad używania podejścia obiektowego $ scope lub kontrolera jako składni. Jest to jednak kwestia wyboru, jednak użycie kontrolera jako składni sprawia, że ​​kod JavaScript kontrolera jest bardziej czytelny i zapobiega wszelkim problemom związanym z tym kontekstem.

Zagnieżdżone kontrolery w podejściu obiektowym $ scope

Mamy dwa kontrolery, jak pokazano na poniższej liście:

myApp.controller("ParentController", function ($scope) {



    $scope.name = "DJ";

    $scope.age = 32;

});

myApp.controller("ChildController", function ($scope) {



    $scope.age = 22;

    $scope.country = "India";



});

Właściwość „age” znajduje się wewnątrz obu kontrolerów i w widoku te dwa kontrolery można zagnieżdżać, jak pokazano na poniższej liście:

<div ng-controller="ParentController">



            <h2>Name :{{name}} </h2>

            <h3>Age:{{age}}</h3>



             <div ng-controller="ChildController">

                    <h2>Parent Name :{{name}} </h2>

                    <h3>Parent Age:{{$parent.age}}</h3>

                    <h3>Child Age:{{age}}</h3>

                    <h3>Country:{{country}}</h3>

             </div>

        </div>

Jak widać, aby uzyskać dostęp do właściwości wieku kontrolera nadrzędnego, używamy zmiennej $ parent.age. Separacja kontekstu nie jest tutaj zbyt jasna. Ale używając kontrolera jako składni, możemy pracować z zagnieżdżonymi kontrolerami w bardziej elegancki sposób. Powiedzmy, że mamy kontrolery, jak pokazano na poniższej liście:

myApp.controller("ParentVMController", function () {

    var vm = this;

    vm.name = "DJ";

    vm.age = 32;

});

myApp.controller("ChildVMController", function () {

    var vm = this;

    vm.age = 22;

    vm.country = "India";



});

W widoku te dwa kontrolery można zagnieżdżać, jak pokazano na poniższej liście:

<div ng-controller="ParentVMController as parent">



            <h2>Name :{{parent.name}} </h2>

            <h3>Age:{{parent.age}}</h3>



            <div ng-controller="ChildVMController as child">

                <h2>Parent Name :{{parent.name}} </h2>

                <h3>Parent Age:{{parent.age}}</h3>

                <h3>Child Age:{{child.age}}</h3>

                <h3>Country:{{child.country}}</h3>

            </div>

 </div>

W kontrolerze jako składni mamy bardziej czytelny kod, a do właściwości nadrzędnej można uzyskać dostęp za pomocą nazwy aliasu kontrolera nadrzędnego zamiast używania składni $ parent.

Zakończę ten post stwierdzeniem, że wybór należy wyłącznie do Ciebie, czy chcesz użyć kontrolera jako składni, czy obiektu $ scope. Nie ma to żadnej wielkiej zalety ani wady, po prostu kontroler jako składnia, którą masz kontrolę nad kontekstem, jest nieco łatwiejszy w użyciu, biorąc pod uwagę wyraźną separację w zagnieżdżonych kontrolerach w widoku.


4

Uważam, że główną zaletą jest bardziej intuicyjny interfejs API, ponieważ metody / właściwości są powiązane bezpośrednio z instancją kontrolera, a nie z obiektem zakresu. Zasadniczo, przy starym podejściu, kontroler staje się tylko dekoracją do budowania obiektu zasięgu.

Oto więcej informacji na ten temat: http://www.syntaxsuccess.com/viewarticle/551798f20c5f3f3c0ffcc9ff


3

Z tego, co przeczytałem, $ scope zostanie usunięty w Angular 2.0, a przynajmniej jak postrzegamy użycie $ scope. Dobrze byłoby zacząć używać kontrolera w miarę zbliżania się wydania 2.0.

Link do wideo tutaj, aby uzyskać więcej dyskusji na ten temat.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.