W tym wpisie wytłumaczę czym jest wstrzykiwanie zależności oraz przybliżę metody służące do tego. Opowiem o zaletach i wadach, każdej z nich. Dodatkowo wspomnę o obiekcie $rootScope oraz zaprezentuje jego działanie w aplikacji demonstracyjnej. Wymienie również obiekty jakie mogą być wstrzykiwane.
Wstrzykiwanie zależności to wzorzec projektowy, służący do zarządzania zależnościami. Korzystając z tego mechanizmu mamy większą kontrole nad czytelnością pisanego przez nas kodu. Wynika to z tego, iż tworzenie jak i używanie zależności są od siebie oddzielone. Możemy z obiektu korzystać w różnych miejscach pisanej aplikacji. Dodatkowo mamy możliwość modyfikacji zależności poprzez dodanie nowej lub usuniecie już istniejącej. Ilość wstrzykiwanych zależności jest dowolna.
Dostęp do zależności
Do obiektu możemy się odwołać dzięki trzech sposobów
- Ze zmiennej globalnej – $rootScope.
- Ze zmiennej lokalnej – $scope.
- Poprzez przekazanie parametru do funkcji wykonującej.
$rootScope to obiekt przechowujący wszystkie instancje obiektów $scope, które są jego potomkami. Jednak warto pamiętać, iż nie należy zaśmiecać globalnego zbioru.
Zmienne lokalne – $scope wymagają tworzenia w miejscu wywołania, co pozbawia możliwości zarządzania zależnościami.
Zatem wstrzykiwanie zależności związane jest z przekazywaniem ich przez parametr. Za wstrzykiwanie odpowiada usługa $injector.
Metody wstrzykiwania zależności
W celu wstrzyknięcia zależności mamy do dyspozycji trzy sposoby:
- Implicit Annotation
- Explicit Annotation
- Usługa $injector
Implicit Annotation
Najprostsza konstrukcja odpowiadająca za wstrzykiwanie zależności. Polega na przekazaniu obiektów jako parametr funkcji tworzącej komponent np. kontroler. Nie jest pozbawiona wad. Metoda ta, rozpoznaje wstrzyknięte zależności po nazwie co ogranicza programistów w nadawaniu nazw. Kolejność podawanych parametrów nie ma znaczenia.
W tej metodzie występuje również minifikacja. To proces usunięcia niepotrzebnych znaków, zdarza się, iż argumenty funkcji mają zmieniane nazwy, co powoduje wystąpienie błędu.
Przykład wstrzykiwania zależności
app.controller("appCtrl", function ($rootScope, $scope) { $scope.name = "Aplikacja 4"; console.log($rootScope.$$childHead.name) console.log($scope.name) })Jak widzimy, dzięki $rootScope możemy się odwołać do konkretnego obiektu $scope.
Explicit Annotation
Sposób ten jest bardzo podobny do omówionego wyżej. Jednak kluczową różnicą jest tablica zawierająca wstrzyknięte zależności oraz jako ostatni element tablicy funkcję wykonującą. Kolejność umieszczanych parametrów w funkcji tym razem ma znaczenie, musi odpowiadać kolejności elementów w tablicy, jednakże nazwy parametrów mogą się różnić od elementów tablicy.
Przykład wstrzykiwania zależności
app.controller("appCtrl", ['$rootScope', '$scope', function ($rootScope, $scope) { $scope.name = "Aplikacja 4"; console.log($rootScope.$$childHead.name) console.log($scope.name) }])Gdybyśmy zamienili parametry kolejnością, to w funkcji odwoływalibyśmy się do $rootScope dzięki parametru $scope, a do $scope dzięki parametru $rootScope.
Usługa $injector
Ostatnią metodą wstrzykiwania zależności jest wykorzystanie usługi $injector. Kolejność musi być taka sama dla usługi jak i dla parametrów funkcji wykonującej. Nazwy parametrów mogą być dowolne.
Przykład wstrzykiwania zależności
var appCtrl = function ($rootScope, $scope) { $scope.name = "Aplikacja 4"; console.log($rootScope.$$childHead.name) console.log($scope.name) } appCtrl.$injector = ['$rootScope', '$scope']; app.controller("appCtrl", appCtrl)Wstrzykiwane obiekty
AngularJS pozwala nam na wstrzykiwanie obiektów takich jak:
- Value
- Factory
- Service
- Provider
- Constant
Przykładowa aplikacja
<!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 #4</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body ng-controller="appCtrl"> <h1>{{name}}</h1> <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", function ($rootScope, $scope) { $scope.name = "Aplikacja 4"; console.log($rootScope.$$childHead.name) console.log($scope.name) }) app.controller("appCtrl", ['$rootScope', '$scope', function ($rootScope, $scope) { $scope.name = "Aplikacja 4"; console.log($rootScope.$$childHead.name) console.log($scope.name) }]) var appCtrl = function ($rootScope, $scope) { $scope.name = "Aplikacja 4"; console.log($rootScope.$$childHead.name) console.log($scope.name) } appCtrl.$injector = ['$rootScope', '$scope']; app.controller("appCtrl", appCtrl) </script> </body> </html>Podsumowanie
Wstrzykiwanie zależność to jedna z ważniejszych rzeczy w AngularJS. Dzięki tej technice mamy większą kontrolę nad pisanym kodem. Z tego wpisu dowiedzieliśmy się, iż mamy trzy rodzaje dostępu do obiektów, jednak wstrzykiwanie z tych wszystkich jest najlepszą praktyką. Mamy również trzy rodzaje dodawania zależności. Osobiście najczęściej wykorzystuję, metodę przedstawioną jako ostatnią.
Pozdrawiam,
sirmarbug