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.