AngularJS: Zrozumienie wzorca projektowego

147

W kontekście tego posta Igora Minara, szefa AngularJS:

MVC vs MVVM vs MVP . Co za kontrowersyjny temat, na który wielu programistów może spędzać wiele godzin debatując i kłócąc się.

Przez kilka lat AngularJS był bliżej MVC (a raczej jednego z jego wariantów po stronie klienta), ale z biegiem czasu i dzięki wielu refaktoryzacjom i ulepszeniom interfejsu API, jest teraz bliżej MVVM - obiekt $ scope można uznać za ViewModel, który jest obecnie ozdobiony funkcją, którą nazywamy kontrolerem .

Możliwość kategoryzacji frameworka i umieszczenia go w jednym z wiader MV * ma kilka zalet. Może pomóc programistom poczuć się bardziej komfortowo z interfejsem API, ułatwiając tworzenie modelu mentalnego reprezentującego aplikację, która jest tworzona za pomocą frameworka. Może również pomóc w ustaleniu terminologii używanej przez programistów.

Powiedziałbym, że wolałbym, aby programiści tworzyli odlotowe aplikacje, które są dobrze zaprojektowane i podążają za oddzielnymi problemami, niż patrzeć, jak marnują czas na kłótnie o bzdury MV *. Z tego powodu niniejszym oświadczam, że AngularJS jest frameworkiem MVW - Model-View-Cokolwiek . Gdzie Cokolwiek oznacza „ cokolwiek działa dla Ciebie ”.

Angular zapewnia dużą elastyczność, aby ładnie oddzielić logikę prezentacji od logiki biznesowej i stanu prezentacji. Użyj go, aby zwiększyć produktywność i łatwość obsługi aplikacji, a nie gorące dyskusje o rzeczach, które ostatecznie nie mają tak dużego znaczenia.

Czy są jakieś zalecenia lub wytyczne dotyczące implementacji wzorca projektowego AngularJS MVW (Model-View-Whokolwiek) w aplikacjach po stronie klienta?

Artem Platonov
źródło
za ... niż zobaczyć, jak marnują czas na kłótnie o bzdury MV *.
Shirgill Farhan
1
Nie potrzebujesz Angulara, aby podążać za wzorcem projektu klasy słów.
przydatneBee

Odpowiedzi:

223

Dzięki ogromnej ilości cennych źródeł otrzymałem kilka ogólnych zaleceń dotyczących implementacji komponentów w aplikacjach AngularJS:


Kontroler

  • Kontroler powinien być tylko warstwą pośrednią między modelem a widokiem. Postaraj się, aby był tak cienki, jak to tylko możliwe.

  • Zdecydowanie zaleca się unikanie logiki biznesowej w kontrolerze. Należy go przenieść do modelu.

  • Kontroler może komunikować się z innymi kontrolerami za pomocą wywołania metody (możliwe, gdy dzieci chcą komunikować się z rodzicem) lub metod $ emit , $ broadcast i $ on . Emitowane i nadawane wiadomości powinny być ograniczone do minimum.

  • Kontroler nie powinien przejmować się prezentacją ani manipulacją DOM.

  • Staraj się unikać zagnieżdżonych kontrolerów . W tym przypadku kontroler nadrzędny jest interpretowany jako model. Zamiast tego wstrzykuj modele jako usługi wspólne.

  • Zakres w kontrolerze powinien być używany do wiązania modelu z widokiem i
    hermetyzowania modelu widoku, jak w przypadku wzorca projektowego modelu prezentacji .


Zakres

Traktuj zakres jako tylko do odczytu w szablonach i tylko do zapisu w kontrolerach . Celem zakresu jest odwoływanie się do modelu, a nie bycie modelem.

Podczas wykonywania dwukierunkowego wiązania (model ng) upewnij się, że nie tworzysz powiązania bezpośrednio z właściwościami zakresu.


Model

Model w AngularJS to singleton zdefiniowany przez usługę .

Model zapewnia doskonały sposób oddzielania danych i wyświetlania.

Modele są głównymi kandydatami do testów jednostkowych, ponieważ zazwyczaj mają dokładnie jedną zależność (pewną formę emitera zdarzeń, w typowym przypadku $ rootScope ) i zawierają wysoce testowalną logikę domeny .

  • Model należy traktować jako realizację konkretnej jednostki. Opiera się na zasadzie pojedynczej odpowiedzialności. Jednostka jest instancją odpowiedzialną za własny zakres powiązanej logiki, która może reprezentować pojedynczą jednostkę w świecie rzeczywistym i opisywać ją w świecie programowania pod względem danych i stanu .

  • Model powinien hermetyzować dane aplikacji i zapewniać interfejs API do uzyskiwania dostępu do tych danych i manipulowania nimi.

  • Model powinien być przenośny, aby można go było łatwo przenosić do podobnej aplikacji.

  • Wyodrębnienie logiki jednostki w modelu ułatwiło zlokalizowanie, aktualizację i konserwację.

  • Model może wykorzystywać metody bardziej ogólnych modeli globalnych, które są wspólne dla całej aplikacji.

  • Staraj się unikać łączenia innych modeli z modelem przy użyciu wstrzykiwania zależności, jeśli nie jest to tak naprawdę zależne od zmniejszenia sprzężenia komponentów i zwiększenia testowalności i użyteczności jednostek .

  • Staraj się unikać detektorów zdarzeń w modelach. Utrudnia ich testowanie i generalnie zabija modele w kategoriach zasady pojedynczej odpowiedzialności.

Implementacja modelu

Ponieważ model powinien zawierać pewną logikę w zakresie danych i stanu, powinien architektonicznie ograniczać dostęp do swoich elementów, dzięki czemu możemy zagwarantować luźne powiązania.

Sposobem na to w aplikacji AngularJS jest zdefiniowanie go za pomocą usługi fabrycznej . Pozwoli nam to bardzo łatwo zdefiniować prywatne właściwości i metody, a także zwrócić publicznie dostępne w jednym miejscu, dzięki czemu będzie naprawdę czytelny dla programisty.

Przykład :

angular.module('search')
.factory( 'searchModel', ['searchResource', function (searchResource) {

  var itemsPerPage = 10,
  currentPage = 1,
  totalPages = 0,
  allLoaded = false,
  searchQuery;

  function init(params) {
    itemsPerPage = params.itemsPerPage || itemsPerPage;
    searchQuery = params.substring || searchQuery;
  }

  function findItems(page, queryParams) {
    searchQuery = queryParams.substring || searchQuery;

    return searchResource.fetch(searchQuery, page, itemsPerPage).then( function (results) {
      totalPages = results.totalPages;
      currentPage = results.currentPage;
      allLoaded = totalPages <= currentPage;

      return results.list
    });
  }

  function findNext() {
    return findItems(currentPage + 1);
  }

  function isAllLoaded() {
    return allLoaded;
  }

  // return public model API  
  return {
    /**
     * @param {Object} params
     */
    init: init,

    /**
     * @param {Number} page
     * @param {Object} queryParams
     * @return {Object} promise
     */
    find: findItems,

    /**
     * @return {Boolean}
     */
    allLoaded: isAllLoaded,

    /**
     * @return {Object} promise
     */
    findNext: findNext
  };
});

Tworzenie nowych instancji

Staraj się unikać fabryki, która zwraca nową możliwą funkcję, ponieważ zaczyna to rozkładać wstrzykiwanie zależności, a biblioteka będzie zachowywać się niezręcznie, szczególnie dla osób trzecich.

Lepszym sposobem osiągnięcia tego samego jest użycie fabryki jako interfejsu API do zwracania kolekcji obiektów z dołączonymi do nich metodami pobierającymi i ustawiającymi.

angular.module('car')
 .factory( 'carModel', ['carResource', function (carResource) {

  function Car(data) {
    angular.extend(this, data);
  }

  Car.prototype = {
    save: function () {
      // TODO: strip irrelevant fields
      var carData = //...
      return carResource.save(carData);
    }
  };

  function getCarById ( id ) {
    return carResource.getById(id).then(function (data) {
      return new Car(data);
    });
  }

  // the public API
  return {
    // ...
    findById: getCarById
    // ...
  };
});

Model globalny

Ogólnie rzecz biorąc, staraj się unikać takich sytuacji i odpowiednio projektuj modele, aby można je było wstrzyknąć do kontrolera i użyć w swoim widoku.

W szczególnym przypadku niektóre metody wymagają globalnej dostępności w aplikacji. Aby było to możliwe, możesz zdefiniować właściwość ' common ' w $ rootScope i powiązać ją z commonModel podczas ładowania aplikacji:

angular.module('app', ['app.common'])
.config(...)
.run(['$rootScope', 'commonModel', function ($rootScope, commonModel) {
  $rootScope.common = 'commonModel';
}]);

Wszystkie twoje globalne metody będą funkcjonować w ramach „ wspólnej ” własności. To jest jakaś przestrzeń nazw .

Ale nie definiuj żadnych metod bezpośrednio w $ rootScope . Może to prowadzić do nieoczekiwanego zachowania, gdy jest używane z dyrektywą ngModel w zakresie widoku, generalnie zaśmiecając zakres i prowadzi do nadpisania metod zakresu.


Ratunek

Zasób umożliwia interakcję z różnymi źródłami danych .

Powinien być wdrażany zgodnie z zasadą pojedynczej odpowiedzialności .

W szczególności jest to serwer proxy wielokrotnego użytku do punktów końcowych HTTP / JSON.

Zasoby są wprowadzane do modeli i dają możliwość wysyłania / pobierania danych.

Wdrażanie zasobów

Fabryka, która tworzy obiekt zasobów, który umożliwia interakcję ze źródłami danych po stronie serwera zgodnymi ze specyfikacją REST.

Zwrócony obiekt zasobu ma metody akcji, które zapewniają zachowania wysokiego poziomu bez konieczności interakcji z usługą $ http niskiego poziomu.


Usługi

Zarówno model, jak i zasób to usługi .

Usługi to niepowiązane, luźno powiązane jednostki funkcjonalności, które są niezależne.

Usługi to funkcja, którą Angular przenosi do aplikacji internetowych po stronie klienta po stronie serwera, gdzie usługi są powszechnie używane od dawna.

Usługi w aplikacjach Angular to obiekty zastępcze, które są połączone ze sobą przy użyciu iniekcji zależności.

Angular oferuje różne rodzaje usług. Każdy ma własne przypadki użycia. Aby uzyskać szczegółowe informacje, przeczytaj artykuł Zrozumienie typów usług .

Spróbuj rozważyć główne zasady architektury usług w swojej aplikacji.

Ogólnie zgodnie z Glosariuszem usług internetowych :

Usługa to abstrakcyjny zasób, który reprezentuje możliwość wykonywania zadań, które tworzą spójną funkcjonalność z punktu widzenia podmiotów dostawców i podmiotów żądających. Aby skorzystać z usługi, musi ona zostać zrealizowana przez konkretnego agenta dostawcy.


Struktura po stronie klienta

Ogólnie rzecz biorąc, strona klienta aplikacji jest podzielona na moduły . Każdy moduł powinien być testowalny jako jednostka.

Spróbuj zdefiniować moduły w zależności od funkcji / funkcjonalności lub widoku , a nie według typu. Zobacz prezentację Misko po szczegóły.

Komponenty modułów można konwencjonalnie pogrupować według typów, takich jak kontrolery, modele, widoki, filtry, dyrektywy itp.

Ale sam moduł pozostaje wielokrotnego użytku , przenoszalny i testowalny .

Programiści mogą również znacznie łatwiej znaleźć niektóre części kodu i wszystkie jego zależności.

Szczegółowe informacje można znaleźć w sekcji Organizacja kodu w dużych aplikacjach AngularJS i JavaScript .

Przykład struktury folderów :

|-- src/
|   |-- app/
|   |   |-- app.js
|   |   |-- home/
|   |   |   |-- home.js
|   |   |   |-- homeCtrl.js
|   |   |   |-- home.spec.js
|   |   |   |-- home.tpl.html
|   |   |   |-- home.less
|   |   |-- user/
|   |   |   |-- user.js
|   |   |   |-- userCtrl.js
|   |   |   |-- userModel.js
|   |   |   |-- userResource.js
|   |   |   |-- user.spec.js
|   |   |   |-- user.tpl.html
|   |   |   |-- user.less
|   |   |   |-- create/
|   |   |   |   |-- create.js
|   |   |   |   |-- createCtrl.js
|   |   |   |   |-- create.tpl.html
|   |-- common/
|   |   |-- authentication/
|   |   |   |-- authentication.js
|   |   |   |-- authenticationModel.js
|   |   |   |-- authenticationService.js
|   |-- assets/
|   |   |-- images/
|   |   |   |-- logo.png
|   |   |   |-- user/
|   |   |   |   |-- user-icon.png
|   |   |   |   |-- user-default-avatar.png
|   |-- index.html

Dobry przykład strukturyzacji aplikacji kątowych jest realizowany przez angular-app - https://github.com/angular-app/angular-app/tree/master/client/src

Uwzględniają to również nowoczesne generatory aplikacji - https://github.com/yeoman/generator-angular/issues/109

Artem Platonov
źródło
5
Mam jedną obawę dotyczącą: „Jest wysoce zalecane, aby unikać logiki biznesowej w kontrolerze. Powinno zostać przeniesione do modelu”. Jednak z oficjalnej dokumentacji można przeczytać: „Ogólnie kontroler nie powinien próbować robić zbyt wiele. Powinien zawierać tylko logikę biznesową potrzebną do pojedynczego widoku.”. Czy mówimy o tym samym?
op1ekun
3
Powiedziałbym - traktuj kontrolera jako model widoku.
Artem Platonov
1
+1. Kilka świetnych rad! 2. Niestety przykład searchModelnie jest zgodny z zaleceniami dotyczącymi ponownego użycia. Byłoby lepiej importować stałe za pośrednictwem constantusługi. 3. Jakieś wyjaśnienie, o co tu chodzi ?:Try to avoid having a factory that returns a new able function
Dmitri Zaitsev
1
Również nadpisanie prototypewłaściwości obiektu przerywa dziedziczenie, zamiast tego można użyćCar.prototype.save = ...
Dmitri Zaitsev
2
@ChristianAichinger, chodzi o naturę łańcucha prototypów JavaScript, który zmusza cię do użycia objectw twoim dwukierunkowym wyrażeniu wiążącym, aby upewnić się, że piszesz do dokładnej właściwości lub setterfunkcji. W przypadku korzystania z właściwości direct z zakresu ( bez kropki ) istnieje ryzyko ukrycia żądanej właściwości docelowej z nowo utworzoną w najbliższym górnym zakresie w łańcuchu prototypów podczas pisania do niej. Lepiej wyjaśnia to prezentacja
Artem
46

Myślę, że podejście Igora do tego, jak widać w cytacie, który podałeś, jest tylko wierzchołkiem góry lodowej o wiele większego problemu.

MVC i jego pochodne (MVP, PM, MVVM) są dobre i eleganckie w ramach jednego agenta, ale architektura serwer-klient jest do wszystkich celów systemem dwuagentowym, a ludzie często mają taką obsesję na punkcie tych wzorców, że zapominają o tym problem jest o wiele bardziej złożony. Próbując przestrzegać tych zasad, w rzeczywistości kończy się wadliwą architekturą.

Zróbmy to krok po kroku.

Wytyczne

Wyświetlenia

W kontekście Angular, widok jest DOM. Wytyczne są następujące:

Robić:

  • Obecna zmienna zakresu (tylko do odczytu).
  • Wywołaj kontroler w celu wykonania akcji.

Nie:

  • Umieść jakąkolwiek logikę.

Wygląda to równie kusząco, krótko i nieszkodliwie:

ng-click="collapsed = !collapsed"

To prawie oznacza każdego programistę, który teraz, aby zrozumieć, jak działa system, musi sprawdzić zarówno pliki Javascript, jak i HTML.

Kontrolery

Robić:

  • Powiąż widok z „modelem”, umieszczając dane w zakresie.
  • Reaguj na działania użytkownika.
  • Zajmij się logiką prezentacji.

Nie:

  • Zajmuj się każdą logiką biznesową.

Powodem ostatniej wytycznej jest to, że kontrolerzy są siostrami poglądów, a nie bytami; ani nie są wielokrotnego użytku.

Można argumentować, że dyrektywy są wielokrotnego użytku, ale dyrektywy również są siostrzanymi widokami (DOM) - nigdy nie miały odpowiadać podmiotom.

Jasne, czasami widoki reprezentują byty, ale to raczej szczególny przypadek.

Innymi słowy, kontrolerzy powinni skupić się na prezentacji - jeśli zastosujesz logikę biznesową, nie tylko prawdopodobnie otrzymasz napompowany, mało zarządzalny kontroler, ale także naruszysz zasadę oddzielenia spraw .

W związku z tym kontrolery w Angular to bardziej model prezentacji lub MVVM .

A więc jeśli kontrolery nie powinny zajmować się logiką biznesową, kto powinien?

Co to jest model?

Twój model klienta jest często niepełny i nieaktualny

Jeśli nie piszesz aplikacji internetowej offline lub aplikacji, która jest strasznie prosta (kilka jednostek), Twój model klienta prawdopodobnie będzie:

  • Częściowy
    • Albo nie ma wszystkich encji (jak w przypadku paginacji)
    • Lub nie ma wszystkich danych (jak w przypadku paginacji)
  • Nieaktualny - jeśli system ma więcej niż jednego użytkownika, w dowolnym momencie nie można mieć pewności, że model, który posiada klient, jest taki sam, jak ten, który posiada serwer.

Prawdziwy model musi trwać

W tradycyjnym MCV model jest jedyną rzeczą, którą się utrwala . Ilekroć mówimy o modelach, należy je kiedyś upierać. Twój klient może dowolnie manipulować modelami, ale dopóki podróż w obie strony do serwera nie zostanie zakończona pomyślnie, praca nie zostanie wykonana.

Konsekwencje

Dwa powyższe punkty powinny służyć jako przestroga - model, który posiada twój klient, może obejmować tylko częściową, przeważnie prostą logikę biznesową.

W związku z tym być może rozsądnie jest, w kontekście klienta, używać małych liter M- więc tak naprawdę jest to mVC , mVP i mVVm . Duży Mjest dla serwera.

Logika biznesowa

Być może jedną z najważniejszych koncepcji dotyczących modeli biznesowych jest to, że można je podzielić na 2 typy (pomijam trzeci pogląd biznesowy, ponieważ jest to historia na inny dzień):

  • Logika domeny - czyli reguły biznesowe przedsiębiorstwa , logika niezależna od aplikacji. Na przykład, podaj model z właściwościami firstNamei sirName, metodę pobierającą, taką jak, getFullName()można uznać za niezależną od aplikacji.
  • Logika aplikacji - inaczej Reguły biznesowe aplikacji , które są specyficzne dla aplikacji. Na przykład sprawdzanie i obsługa błędów.

Należy podkreślić, że obie te kwestie w kontekście klienta nie„prawdziwą” logiką biznesową - zajmują się tylko tą częścią, która jest ważna dla klienta. Logika aplikacji (nie logika domeny) powinna odpowiadać za ułatwianie komunikacji z serwerem i większości interakcji użytkownika; podczas gdy logika domeny jest w dużej mierze niewielka, specyficzna dla jednostki i oparta na prezentacji.

Pozostaje pytanie - gdzie wrzucasz je w aplikacji kątowej?

Architektura 3 vs 4 warstwowa

Wszystkie te frameworki MVW używają 3 warstw:

Trzy koła.  Wewnętrzna - model, środkowa - kontroler, zewnętrzna - widok

W przypadku klientów są jednak dwa podstawowe problemy:

  • Model jest częściowy, nieaktualny i nie jest trwały.
  • Brak miejsca na logikę aplikacji.

Alternatywą dla tej strategii jest strategia 4-warstwowa :

4 okręgi, od wewnętrznego do zewnętrznego - reguły biznesowe przedsiębiorstwa, reguły biznesowe aplikacji, adaptery interfejsów, struktury i sterowniki

Prawdziwym problemem jest tutaj warstwa reguł biznesowych aplikacji (przypadki użycia), która często źle wpływa na klientów.

Warstwa ta jest realizowana przez interaktory (wujek Bob), co jest właściwie tym, co Martin Fowler nazywa warstwą usług skryptu operacyjnego .

Konkretny przykład

Rozważ następującą aplikację internetową:

  • Aplikacja wyświetla listę użytkowników podzieloną na strony.
  • Użytkownik klika „Dodaj użytkownika”.
  • Model otwiera się z formularzem do wypełnienia danych użytkownika.
  • Użytkownik wypełnia formularz i naciska przycisk Prześlij.

Teraz powinno się wydarzyć kilka rzeczy:

  • Formularz powinien być zatwierdzony przez klienta.
  • Żądanie zostanie wysłane do serwera.
  • Jeśli wystąpił błąd, należy go załatwić.
  • Lista użytkowników może, ale nie musi (z powodu paginacji) wymagać aktualizacji.

Gdzie to wszystko rzucimy?

Jeśli twoja architektura obejmuje kontroler, który wywołuje $resource, wszystko to będzie się działo w kontrolerze. Ale jest lepsza strategia.

Proponowane rozwiązanie

Poniższy diagram pokazuje, jak można rozwiązać powyższy problem, dodając kolejną warstwę logiki aplikacji w klientach Angular:

4 pola - DOM wskazuje na kontroler, który wskazuje na logikę aplikacji, która wskazuje na $ zasób

Więc dodajemy warstwę między kontrolerem do $ resource, tę warstwę (nazwijmy to interaktorem ):

  • To usługa . W przypadku użytkowników można to nazwać UserInteractor.
  • Zapewnia metody odpowiadające przypadkom użycia , hermetyzując logikę aplikacji .
  • To kontroluje żądania skierowane do serwera. Zamiast wywoływania przez kontroler $ resource z dowolnymi parametrami, ta warstwa zapewnia, że ​​żądania wysyłane do serwera zwracają dane, na których może działać logika domeny.
  • Ozdabia zwróconą strukturę danych prototypem logiki domeny .

I tak, z wymaganiami konkretnego przykładu powyżej:

  • Użytkownik klika „Dodaj użytkownika”.
  • Kontroler prosi interaktor o pusty model użytkownika, który jest ozdobiony metodą logiki biznesowej, na przykład validate()
  • Po przesłaniu kontroler wywołuje validate()metodę modelu .
  • Jeśli się nie powiedzie, kontroler obsłuży błąd.
  • Jeśli się powiedzie, kontroler wywołuje interaktor z createUser()
  • Interaktor wywołuje $ resource
  • Po uzyskaniu odpowiedzi interaktor deleguje wszelkie błędy do kontrolera, który je obsługuje.
  • Po pomyślnej odpowiedzi interactor zapewnia, że ​​w razie potrzeby lista użytkowników zostanie zaktualizowana.
Izhaki
źródło
Więc AngularJS jest zdefiniowane jako MVW (gdzie W oznacza cokolwiek), ponieważ mogę wybrać kontroler (z całą logiką biznesową) lub View Model / Presenter (bez logiki biznesowej, ale tylko trochę kodu do wypełnienia widoku) z BL w osobna usługa? Czy mam rację?
BAD_SEED
Najlepsza odpowiedź. Czy masz prawdziwy przykład w GitHubie 4-warstwowej aplikacji kątowej?
RPallas
1
@RPallas, No I don't (szkoda, że ​​nie mam na to czasu). Obecnie testujemy architekturę, w której „logika aplikacji” jest tylko pośrednikiem granicznym; resolver między nim a kontrolerem i model widoku, który ma pewną logikę widoku. Wciąż eksperymentujemy, a więc nie 100% zalet i wad. Ale kiedy już to zrobię, mam nadzieję, że napiszę gdzieś bloga.
Izhaki,
1
@heringer Zasadniczo wprowadziliśmy modele - konstrukcje OOP, które reprezentują jednostki domeny. To te modele komunikują się z zasobami, a nie kontrolerami. Hermetyzują logikę domeny. Kontrolery wywołują modele, które z kolei wywołują zasoby.
Izhaki
1
@ alex440 Nie. Chociaż minęły już dwa miesiące, kiedy poważny wpis na blogu na ten temat jest na wyciągnięcie ręki. Zbliża się Boże Narodzenie - prawdopodobnie wtedy.
Izhaki
5

Drobny problem w porównaniu ze świetnymi radami zawartymi w odpowiedzi Artema, ale jeśli chodzi o czytelność kodu, uznałem, że najlepiej jest zdefiniować API całkowicie wewnątrz returnobiektu, aby zminimalizować przechodzenie tam iz powrotem w kodzie, aby sprawdzić, gdzie są zdefiniowane zmienne:

angular.module('myModule', [])
// or .constant instead of .value
.value('myConfig', {
  var1: value1,
  var2: value2
  ...
})
.factory('myFactory', function(myConfig) {
  ...preliminary work with myConfig...
  return {
    // comments
    myAPIproperty1: ...,
    ...
    myAPImethod1: function(arg1, ...) {
    ...
    }
  }
});

Jeśli returnobiekt zacznie wyglądać na „zbyt zatłoczony”, oznacza to, że Usługa robi za dużo.

Dmitri Zaitsev
źródło
0

AngularJS nie implementuje MVC w tradycyjny sposób, raczej implementuje coś bliższego MVVM (Model-View-ViewModel), ViewModel można również nazwać binder (w przypadku kątowym może to być $ scope). Model -> Jak wiemy, model w angular może być po prostu zwykłymi, starymi obiektami JS lub danymi w naszej aplikacji

Widok -> widok w angularJS to kod HTML, który został przeanalizowany i skompilowany przez angularJS przez zastosowanie dyrektyw, instrukcji lub powiązań. Głównym punktem jest tutaj kątowe, dane wejściowe to nie tylko zwykły ciąg HTML (innerHTML), a raczej to DOM tworzony przez przeglądarkę.

ViewModel -> ViewModel jest w rzeczywistości łącznikiem / pomostem między widokiem a modelem w przypadku angularJS jest to $ scope, aby zainicjować i rozszerzyć kontroler $ scope, którego używamy.

Jeśli chcę podsumować odpowiedź: W aplikacji angularJS $ scope ma odniesienie do danych, Kontroler kontroluje zachowanie, a Widok obsługuje układ, współdziałając z kontrolerem, aby odpowiednio się zachowywał.

Ashutosh
źródło
-1

Aby uściślić to pytanie, Angular używa różnych wzorców projektowych, które już napotkaliśmy w naszym zwykłym programowaniu. 1) Kiedy rejestrujemy naszych kontrolerów lub dyrektywy, fabrykę, usługi itp. W odniesieniu do naszego modułu. Tutaj ukrywa dane z globalnej przestrzeni. Co to jest wzorzec modułu . 2) Kiedy angular używa swojego brudnego sprawdzania do porównywania zmiennych zakresu, tutaj używa wzorca obserwatora . 3) Wszystkie zakresy nadrzędne podrzędne w naszych kontrolerach używają wzorca prototypowego. 4) W przypadku wstrzykiwania usług używa wzorca fabrycznego .

Ogólnie rzecz biorąc, do rozwiązywania problemów wykorzystuje różne znane wzorce projektowe.

Naveen Reddy
źródło