W tym wpisie zajmę się składnią controller as, a także możliwym utworzeniem kontrolera bez użycia usługi $scope przy pomocy tej skladni. Zaprezentuje, aplikację napisaną z wykorzystaniem obu metod, tak aby móc zobaczyć różnice w kodzie pomiędzy kontrolerem wykorzystującym wstrzyknięty obiekt $scope, a kontrolerem wiążącym właściwości oraz metody za pomoca this.
Controller As w teorii
Od wersji AngularJS 1.2 została udostępniona składnia controller as, jednak nadal w polskim internecie czy książkach mamy przykłady pokazujące działanie omawianego frameworka w oparciu o usługę $scope. Zalecane jest obecnie tworzenie aplikacji w oparciu o dziś omawianą metodę, a także na komponentach, które zostaną przedstawione w kolejnym wpisie cyklu.
Projektowanie aplikacji z wykorzystaniem $scope uznane zostało za przestarzałe i nawet przy małych aplikacjach zalecane jest wykorzystywanie konstrukcji controller as. Obiekt $scope wykorzystywany jest jedynie przy usługach jakie oferuje np. $watch(), $emit() czy $on().
Aplikacja kliker
To prosta aplikacja, której zadaniem będzie pokazanie różnic w implementacji obu metod. Jej zadanie to zliczanie liczby kliknięć w przycisk. Zatem będziemy mieć metodę odpowiedzialną za obsługę kliknięcia oraz właściwość przechowująca ilość kliknięć. Przejdźmy teraz do implementacji z wykorzystaniem obiektu $scope.
Implementacja $scope
<!DOCTYPE html> <html lang="pl" ng-app="app"> <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>AngularJS #8</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> .panel-default { margin-top: 2em; padding: 1em; } .btn { width: 100% } </style> </head> <body ng-controller="appCtrl"> <h1 class="text-center">AngularJS #8</h1> <div class="row"> <div class="col-md-4 col-md-offset-4 panel panel-default"> <h1 class="text-center">Clicked {{count}}</h1> <button class="btn btn-default" ng-click="clicked()">Click!</button> </div> </div> <script src="https://code.jquery.com/jquery-3.2.1.slim.js" integrity="sha256-tA8y0XqiwnpwmOIl3SGAcFl2RvxHjA8qp0+1uCGmRmg=" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script> <script> var app = angular.module("app", []); app.controller("appCtrl", ['$scope', appCtrl]); function appCtrl ($scope) { $scope.count = 0; $scope.clicked = function () { $scope.count++; } } </script> </body> </html>
W kodzie JS jak zawsze tworzymy moduł naszej aplikacji, a następnie deklarujemy kontroler. Drugim parametrem jest tablica składająca się z dwóch elementów. Pierwszy to obiekt $scope, a drugi to funkcja, której ciało znajduje się poniżej zadeklarowanego kontrolera.
Funkcja ta, odpowiada za całą obsługę utworzonego kontrolera. W parametrze przekazany jest obiekt $scope, któremu przypisana jest właściwość count z wartością 0. Poza tą właściwością przypisana jest również metoda służąca do inkrementacji właściwości count. Jedną z zalet tego rozwiązania jest większa czytelność kodu zwłaszcza, gdy mamy sytuacje, kiedy w jednym pliku html występuje wiele kontrolerów.
Teraz przechodzimy do pliku index.html, gdzie wprowadzamy nasz kontroler w dyrektywie ng-controller.
<body ng-controller="appCtrl">
Do pól z obiektu $scope odwołujemy się za pomocą nazw właściwości jakie nadaliśmy w naszej funkcji.
<h1 class="text-center">Clicked {{count}}</h1> <button class="btn btn-default" ng-click="clicked()">Click!</button>
Implementacja controller as
Teraz omówię drugi sposób tworzenia kontrolera bez wykorzystywania obiektu $scope.
<!DOCTYPE html> <html lang="pl" ng-app="app"> <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>AngularJS #8</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> .panel-default { margin-top: 2em; padding: 1em; } .btn { width: 100% } </style> </head> <body ng-controller="appCtrl as app"> <h1 class="text-center">AngularJS #8</h1> <div class="row"> <div class="col-md-4 col-md-offset-4 panel panel-default"> <h1 class="text-center">Clicked {{app.count}}</h1> <button class="btn btn-default" ng-click="app.clicked()">Click!</button> </div> </div> <script src="https://code.jquery.com/jquery-3.2.1.slim.js" integrity="sha256-tA8y0XqiwnpwmOIl3SGAcFl2RvxHjA8qp0+1uCGmRmg=" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script> <script> var app = angular.module("app", []); app.controller("appCtrl", appCtrl); function appCtrl () { var ctrl = this; ctrl.count = 0; ctrl.clicked = function () { ctrl.count++; } } </script> </body> </html>
Podobnie jak wcześniej tworzymy moduł naszej aplikacji. Następnie przystępujemy do utworzenia kontrolera, jednak tym razem drugim parametrem jest nazwa funkcji, która obsługuje utworzony przez nas kontroler. Na początku tej funkcji deklarujemy zmienną ctrl i przypisujemy jej this, czyli odwołanie do funkcji (funkcja ta jest wywołana podczas tworzenia kontrolera, zatem this odwołuje się do utworzonego kontrolera). Nazwa tej zmiennej pochodzi od słowa controller.
Kolejnym korkiem jest utworzenie wartości count zaliczającej ilość kliknięć. Na koniec tworzymy metodę odpowiedzialną za inkrementacje pola count.
Teraz przejdźmy do pliku z rozszerzeniem .html, tutaj mamy kilka zmian.
<body ng-controller="appCtrl as app">
Przy wprowadzeniu kontrolera nie podajemy już samej nazwy, ale dodatkowo wstawiamy słowo kluczowe as oraz nazwę, przez którą będziemy się odwoływać do niego. Tak jak na przykładzie powyżej.
Kolejną zmianą jest, odwoływanie się do właściwości i metod. Wynikają one ze sposobu deklaracji kontrolera. Teraz przed podaniem pola czy metody należy wcześniej wstawić nazwę podaną po słowie as w dyrektywie ng-controller.
<h1 class="text-center">Clicked {{app.count}}</h1> <button class="btn btn-default" ng-click="app.clicked()">Click!</button>
Efekt działania aplikacji
Podsumowanie
W tym wpisie dowiedzieliśmy się, w jaki inny sposób możemy tworzyć kontrolery. Porównaliśmy różnice w sposobie zapisu na podstawie prostej aplikacji, która liczy kliknięcia w przycisk. Dzięki temu mogliśmy utworzyć kontroler bez wstrzykiwania obiektu $scope. W kolejnym wpisie przedstawię, w jaki sposób tworzy się komponenty w AngularJS, tak abyśmy mogli w kolejnych wpisach pracować na kodzie, który jest rekomendowany.
Jeśli zaciekawił Cie ten wpis i chcesz być na bieżąco z kolejnymi to zachęcam do polubienia mojego fanpage Bugajsky.