Który uważa się za lepszy:
- posiadający dyrektywę, która bezpośrednio współdziała z usługami
lub
- mając dyrektywę, która ujawnia pewne haczyki, z którymi kontroler może wiązać zachowanie (obejmujące usługi)?
Który uważa się za lepszy:
lub
Odpowiedzi:
Dyrektywa jest najlepsza (jako ogólna zasada), gdy jest krótka (pod względem kodu), (potencjalnie) do ponownego użycia i ma ograniczony zakres pod względem funkcjonalności. Stworzenie dyrektywy, która zawiera interfejs użytkownika i zależy od usługi (zakładam, że obsługuje połączenie z backendem), nie tylko daje jej 2 funkcje funkcjonalne, a mianowicie:
ale także sprawia, że jest mniej przydatny do ponownego użycia, ponieważ nie można go ponownie użyć z inną usługą lub z innym interfejsem użytkownika (przynajmniej niełatwo).
Przy podejmowaniu tych decyzji, często w porównaniu do wbudowanego elementów HTML, na przykład <input>
, <textarea>
albo <form>
: są one całkowicie niezależne od konkretnego zaplecza. HTML5 nadało temu <input>
elementowi kilka dodatkowych typów, np. date
Które wciąż są niezależne od backendu i gdzie dokładnie idą dane lub jak są używane. Są to wyłącznie elementy interfejsu. Twoje niestandardowe widżety, zbudowane przy użyciu dyrektyw, myślę, że jeśli to możliwe, powinny stosować ten sam wzór.
To jednak nie koniec historii. Wychodząc poza analogię z wbudowanymi elementami HTML, możesz tworzyć dyrektywy wielokrotnego użytku, które wywołują usługi, i używać dyrektywy o czystym interfejsie użytkownika, tak jak może to zrobić <textarea>
. Powiedz, że chcesz użyć kodu HTML w następujący sposób:
<document document-url="'documents/3345.html'">
<document-data></document-data>
<comments></comments>
<comment-entry></comment-entry>
</document>
Aby zakodować commentEntry
dyrektywę, możesz stworzyć bardzo małą dyrektywę, która zawiera tylko kontroler, który łączy usługę z widgetem interfejsu użytkownika. Coś jak:
app.directive('commentEntry', function (myService) {
return {
restrict: 'E',
template: '<comment-widget on-save="save(data)" on-cancel="cancel()"></comment-widget>',
require: '^document',
link: function (scope, iElement, iAttrs, documentController) {
// Allow the controller here to access the document controller
scope.documentController = documentController;
},
controller: function ($scope) {
$scope.save = function (data) {
// Assuming the document controller exposes a function "getUrl"
var url = $scope.documentController.getUrl();
myService.saveComments(url, data).then(function (result) {
// Do something
});
};
}
};
});
Biorąc to do skrajności, być może nigdy nie będziesz musiał mieć ręcznego ng-controller
atrybutu w kodzie HTML: możesz to wszystko zrobić za pomocą dyrektyw, o ile każda z nich ma bezpośrednio rolę „interfejsu użytkownika” lub rolę „danych”.
Jest jedna wada, o której powinienem wspomnieć: daje więcej „ruchomych części” aplikacji, co dodaje nieco złożoności. Jeśli jednak każda część ma wyraźną rolę i ma się dobrze (testowana jednostka + E2E), argumentowałbym, że jest tego warta i przynosi ogólne korzyści w dłuższej perspektywie.
Pozwól mi nie zgodzić się z odpowiedzią Michała Charemzy.
Chociaż jego odpowiedź jest teoretycznie poprawna, nie jest bardzo praktyczna w prawdziwym świecie.
Mówię to, ponieważ tak myślałem i próbowałem wymusić to w dużej aplikacji z prawdziwego świata, którą buduję ja i mój zespół, a to stało się zbyt kłopotliwe.
Analogia do języka HTML nie jest dobra, ponieważ nie powinieneś dążyć do budowania dyrektyw o ogólnym przeznaczeniu, które można wielokrotnie wykorzystywać, ponieważ nie budujesz ogólnej aplikacji, takiej jak przeglądarka internetowa.
Zamiast tego należy użyć dyrektyw, aby zbudować język specyficzny dla domeny (DSL) dla aplikacji, który działa we własnej domenie.
Nie oznacza to, że wszystkie dyrektywy nie powinny być ogólne. Niektóre mogą być, jeśli jest to w ich naturze. Jeśli tworzysz niestandardowy selektor dat, z pewnością uczyń go ogólnym i można go ponownie używać w różnych aplikacjach.
Ale jeśli budujesz coś w rodzaju pola logowania, które łączy się z zapleczem, po prostu zrób to.
Jedyną ogólną zasadą powinno być: nigdy nie powielaj kodu (abstrakcyjne małe fragmenty do fabryk i usług) i nie pozwalaj na jego testowanie poprzez wstrzykiwanie zależności. Na szczęście w przypadku Angulara to bułka z masłem.
Nie komplikuj. :)
Myślę, że pytanie „czy dyrektywa powinna wchodzić w interakcje z usługą” zależy od tego, co robi twoja usługa.
Miałem dyrektywy współpracujące z usługami, które nie robią nic z żądaniami HTTP i myślę, że to dobry wzorzec. Usługi / fabryki świetnie nadają się do enkapsulacji logiki zorientowanej na dane, a dyrektywy świetnie nadają się do enkapsulacji logiki zorientowanej na prezentację. Określony cel usług w dokumentach Angular to: „Możesz używać usług do organizowania i udostępniania kodu w swojej aplikacji”. To dość szerokie, ale usługi mogą zostać wykorzystane do osiągnięcia tego celu w dyrektywach.
Biorąc to pod uwagę, w niektórych przypadkach rozumiem pragnienie, aby dyrektywy nie wysyłały bezpośrednio żądań HTTP. Znowu zależy to od usługi i sposobu organizacji usług.
Zgodnie ze strukturą AngularJS powinniśmy singletonować fabryki / usługi w celu uzyskiwania dowolnych danych z serwera. Aby te fabryki mogły być ponownie wykorzystane w różnych aplikacjach bez przepisywania tego samego. Cóż, wewnątrz dyrektywy możemy zadzwonić do tych fabryk, aby pobrać dane z Api / serwera.