AngularJS vs. jQuery
AngularJS i jQuery przyjmują bardzo różne ideologie. Jeśli pochodzisz z jQuery, niektóre różnice mogą cię zaskoczyć. Angular może cię zdenerwować.
To normalne, powinieneś przepchnąć się. Kątowe jest tego warte.
Duża różnica (TLDR)
jQuery daje zestaw narzędzi do wybierania dowolnych bitów DOM i wprowadzania do nich zmian ad-hoc. Kawałek po kawałku możesz zrobić praktycznie wszystko.
Zamiast tego AngularJS daje ci kompilator .
Oznacza to, że AngularJS odczytuje cały DOM od góry do dołu i traktuje go jako kod, dosłownie jako instrukcje dla kompilatora. Przechodząc przez DOM, szuka określonych dyrektyw ( dyrektyw kompilatora), które mówią kompilatorowi AngularJS, jak się zachować i co robić. Dyrektywy to małe obiekty pełne JavaScript, które można dopasować do atrybutów, tagów, klas, a nawet komentarzy.
Gdy kompilator Angular stwierdzi, że element DOM pasuje do określonej dyrektywy, wywołuje funkcję dyrektywy, przekazując jej element DOM, dowolne atrybuty, bieżący zakres $ (który jest lokalnym magazynem zmiennych) i kilka innych przydatnych bitów. Te atrybuty mogą zawierać wyrażenia, które mogą być interpretowane przez dyrektywę i które mówią jej, jak renderować i kiedy należy się przerysować.
Dyrektywy mogą z kolei pobierać dodatkowe komponenty Angular, takie jak kontrolery, usługi itp. To, co wychodzi na dół kompilatora, to w pełni ukształtowana aplikacja internetowa, podłączona i gotowa do pracy.
Oznacza to, że Angular jest oparty na szablonie . Twój szablon obsługuje JavaScript, a nie na odwrót. Jest to radykalne odwrócenie ról i całkowite przeciwieństwo dyskretnego JavaScript, który piszemy od około 10 lat. To może trochę przyzwyczaić się.
Jeśli brzmi to jak zbyt nakazowe i ograniczające, nic nie może być dalsze od prawdy. Ponieważ AngularJS traktuje kod HTML jako kod, w aplikacji sieciowej występuje ziarnistość na poziomie HTML . Wszystko jest możliwe, a większość rzeczy jest zaskakująco łatwa po wykonaniu kilku skoków koncepcyjnych.
Zejdźmy do sedna.
Po pierwsze, Angular nie zastępuje jQuery
Angular i jQuery robią różne rzeczy. AngularJS zapewnia zestaw narzędzi do tworzenia aplikacji internetowych. jQuery daje głównie narzędzia do modyfikowania DOM. Jeśli jQuery jest obecny na twojej stronie, AngularJS użyje go automatycznie. Jeśli tak nie jest, AngularJS jest dostarczany z jQuery Lite, która jest odciętą, ale wciąż doskonale użyteczną wersją jQuery.
Misko lubi jQuery i nie sprzeciwia się używaniu go. Jednak w miarę postępów przekonasz się, że możesz wykonać prawie całą swoją pracę za pomocą kombinacji zakresu, szablonów i dyrektyw, i powinieneś preferować ten przepływ pracy tam, gdzie to możliwe, ponieważ twój kod będzie bardziej dyskretny, konfigurowalny i więcej Kątowy.
Jeśli używasz jQuery, nie powinieneś posypywać go wszędzie. Prawidłowe miejsce do manipulacji DOM w AngularJS znajduje się w dyrektywie. Więcej na ten temat później.
Dyskretny JavaScript z Selektorami vs. Deklaratywne szablony
jQuery jest zwykle stosowany dyskretnie. Twój kod JavaScript jest umieszczony w nagłówku (lub stopce) i jest to jedyne miejsce, o którym wspomniano. Używamy selektorów do wybierania fragmentów strony i pisania wtyczek w celu modyfikacji tych części.
JavaScript jest pod kontrolą. HTML ma całkowicie niezależne istnienie. Twój HTML pozostaje semantyczny nawet bez JavaScript. Atrybuty Onclick są bardzo złą praktyką.
Jedną z pierwszych rzeczy, które zauważysz w AngularJS, jest to, że niestandardowe atrybuty są wszędzie . Twój HTML będzie zaśmiecony atrybutami ng, które są zasadniczo atrybutami onClick na sterydach. Są to dyrektywy (dyrektywy kompilatora) i są jednym z głównych sposobów zaczepienia szablonu do modelu.
Kiedy po raz pierwszy to zobaczysz, możesz ulec pokusie, aby napisać AngularJS jako staroświecki JavaScript uciążliwy (tak jak na początku). W rzeczywistości AngularJS nie przestrzega tych zasad. W AngularJS Twój HTML5 jest szablonem. Jest on kompilowany przez AngularJS w celu stworzenia twojej strony internetowej.
To pierwsza duża różnica. Aby jQuery, twoja strona internetowa była DOM, którym można manipulować. Dla AngularJS twój HTML to kod do skompilowania. AngularJS odczytuje całą stronę internetową i dosłownie kompiluje ją w nową stronę internetową za pomocą wbudowanego kompilatora.
Twój szablon powinien być deklaratywny; jego znaczenie powinno być jasne, po prostu je czytając. Używamy niestandardowych atrybutów o znaczących nazwach. Tworzymy nowe elementy HTML, znowu o znaczących nazwach. Projektant z minimalną znajomością HTML i bez umiejętności kodowania może odczytać szablon AngularJS i zrozumieć, co robi. On lub ona może dokonywać modyfikacji. To jest sposób kątowy.
Szablon znajduje się na siedzeniu kierowcy.
Jednym z pierwszych pytań, które zadałem sobie podczas uruchamiania AngularJS i przeglądania samouczków, jest: „Gdzie jest mój kod?” . Nie napisałem JavaScript, a mimo to mam takie zachowanie. Odpowiedź jest oczywista. Ponieważ AngularJS kompiluje DOM, AngularJS traktuje Twój HTML jako kod. W wielu prostych przypadkach często wystarczy po prostu napisać szablon i pozwolić AngularJS skompilować go dla aplikacji.
Twój szablon napędza twoją aplikację. Jest traktowany jak DSL . Piszesz komponenty AngularJS, a AngularJS zajmie się ich wciągnięciem i udostępnieniem we właściwym czasie w oparciu o strukturę twojego szablonu. To bardzo różni się od standardowego wzorca MVC , w którym szablon jest tylko do wydruku.
Na przykład jest bardziej podobny do XSLT niż Ruby on Rails .
Jest to radykalna inwersja kontroli, do której trzeba się przyzwyczaić.
Przestań próbować prowadzić aplikację z JavaScript. Niech szablon steruje aplikacją, a AngularJS zajmie się połączeniem komponentów. To także jest sposób kątowy.
Semantyczny HTML a modele semantyczne
Dzięki jQuery strona HTML powinna zawierać znaczącą treść semantyczną. Jeśli JavaScript jest wyłączony (przez użytkownika lub wyszukiwarkę), twoje treści pozostaną dostępne.
Ponieważ AngularJS traktuje Twoją stronę HTML jako szablon. Szablon nie powinien być semantyczny, ponieważ treść jest zazwyczaj przechowywana w modelu, który ostatecznie pochodzi z interfejsu API. AngularJS kompiluje Twój DOM z modelem, aby utworzyć semantyczną stronę internetową.
Twoje źródło HTML nie jest już semantyczne, zamiast tego interfejs API i skompilowany DOM są semantyczne.
W AngularJS, co oznacza, że żyje w modelu, HTML jest tylko szablonem, tylko do wyświetlania.
W tym momencie prawdopodobnie masz wiele pytań dotyczących SEO i dostępności, i słusznie. Tutaj są otwarte problemy. Większość czytników ekranu będzie teraz analizować JavaScript. Wyszukiwarki mogą również indeksować treści AJAXed . Niemniej jednak upewnij się, że używasz adresów URL typu pushstate i masz przyzwoitą mapę witryny. Tutaj znajduje się omówienie problemu: https://stackoverflow.com/a/23245379/687677
Rozdzielenie obaw (SOC) vs. MVC
Separacja problemów (SOC) to wzorzec, który wyrósł w ciągu wielu lat tworzenia stron internetowych z różnych powodów, w tym SEO, dostępności i niezgodności przeglądarki. To wygląda tak:
- HTML - znaczenie semantyczne. HTML powinien być samodzielny.
- CSS - Stylizacja, bez CSS strona jest nadal czytelna.
- JavaScript - zachowanie, bez skryptu zawartość pozostaje.
Ponownie, AngularJS nie gra według swoich zasad. W jednym uderzeniu AngularJS usuwa dekadę otrzymanej mądrości i zamiast tego implementuje wzór MVC, w którym szablon nie jest już semantyczny, ani trochę.
To wygląda tak:
- Model - twoje modele zawierają dane semantyczne. Modele są zwykle obiektami JSON . Modele istnieją jako atrybuty obiektu o nazwie $ scope. Możesz także przechowywać przydatne funkcje narzędziowe w $ scope, do których szablony mają dostęp.
- Widok - Twoje widoki są napisane w HTML. Widok zwykle nie jest semantyczny, ponieważ dane znajdują się w modelu.
- Kontroler - Twój kontroler to funkcja JavaScript, która przechwytuje widok do modelu. Jego funkcją jest inicjalizacja $ scope. W zależności od aplikacji może być konieczne utworzenie kontrolera. Na stronie możesz mieć wiele kontrolerów.
MVC i SOC nie znajdują się na przeciwległych końcach tej samej skali, lecz na zupełnie innych osiach. SOC nie ma sensu w kontekście AngularJS. Musisz o tym zapomnieć i iść dalej.
Jeśli, podobnie jak ja, przeżyłeś wojny przeglądarkowe, możesz uznać ten pomysł za obraźliwy. Poradzić sobie, to będzie tego warte, obiecuję.
Wtyczki a dyrektywy
Wtyczki rozszerzają jQuery. Dyrektywy AngularJS rozszerzają możliwości twojej przeglądarki.
W jQuery definiujemy wtyczki, dodając funkcje do jQuery.prototype. Następnie podłączamy je do DOM, wybierając elementy i wywołując wtyczkę na wyniku. Chodzi o rozszerzenie możliwości jQuery.
Na przykład, jeśli chcesz mieć karuzelę na swojej stronie, możesz zdefiniować nieuporządkowaną listę cyfr, być może owiniętą w element nawigacyjny. Możesz następnie napisać jQuery, aby wybrać listę na stronie i zmienić jej styl jako galerię z limitami czasu na animację przesuwaną.
W AngularJS definiujemy dyrektywy. Dyrektywa jest funkcją, która zwraca obiekt JSON. Ten obiekt informuje AngularJS, jakich elementów DOM należy szukać i jakie zmiany w nich wprowadzić. Dyrektywy są podłączone do szablonu za pomocą atrybutów lub elementów, które wymyśliłeś. Chodzi o rozszerzenie możliwości HTML o nowe atrybuty i elementy.
AngularJS polega na rozszerzeniu możliwości natywnego wyglądu HTML. Powinieneś pisać HTML, który wygląda jak HTML, rozszerzony o niestandardowe atrybuty i elementy.
Jeśli chcesz karuzeli, po prostu użyj <carousel />
elementu, a następnie zdefiniuj dyrektywę, aby pobrać szablon i sprawić, by ten frajer działał.
Wiele małych dyrektyw vs. duże wtyczki z przełącznikami konfiguracji
JQuery ma tendencję do pisania świetnych dużych wtyczek, takich jak lightbox, które następnie konfigurujemy, przekazując liczne wartości i opcje.
To błąd w AngularJS.
Weź przykład listy rozwijanej. Pisząc rozwijaną wtyczkę, możesz ulec pokusie kodowania w modułach obsługi kliknięć, być może funkcji dodania szewronu, który jest w górę lub w dół, być może zmień klasę rozwiniętego elementu, pokaż ukryj menu, wszystkie przydatne rzeczy.
Aż chcesz wprowadzić małą zmianę.
Załóżmy, że masz menu, które chcesz rozwinąć po najechaniu myszą. Cóż, teraz mamy problem. Nasza wtyczka ma dla nas funkcję obsługi kliknięć. Będziemy musieli dodać opcję konfiguracji, aby działała inaczej w tym konkretnym przypadku.
W AngularJS piszemy mniejsze dyrektywy. Nasza dyrektywa w sprawie rozwijania byłaby absurdalnie mała. Może utrzymywać stan złożony i zapewniać metody fold (), rozkładanie () lub przełączanie (). Te metody po prostu zaktualizują $ scope.menu.visible, który jest wartością logiczną utrzymującą stan.
Teraz w naszym szablonie możemy to połączyć:
<a ng-click="toggle()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
Potrzebujesz aktualizacji po najechaniu kursorem myszy?
<a ng-mouseenter="unfold()" ng-mouseleave="fold()">Menu</a>
<ul ng-show="menu.visible">
...
</ul>
Szablon napędza aplikację, dzięki czemu uzyskujemy szczegółowość na poziomie HTML. Jeśli chcemy wprowadzić wyjątki dla poszczególnych przypadków, szablon ułatwia to.
Zamknięcie a zakres $
Wtyczki JQuery są tworzone w zamknięciu. Prywatność jest utrzymywana w ramach tego zamknięcia. Od Ciebie zależy utrzymanie łańcucha zasięgu w ramach tego zamknięcia. Naprawdę masz dostęp tylko do zestawu węzłów DOM przekazanych do wtyczki przez jQuery, a także do wszystkich zmiennych lokalnych zdefiniowanych w zamknięciu i wszelkich zdefiniowanych przez Ciebie globałów. Oznacza to, że wtyczki są całkowicie samodzielne. To dobrze, ale może stać się restrykcyjne podczas tworzenia całej aplikacji. Próba przekazywania danych między sekcjami strony dynamicznej staje się obowiązkiem.
AngularJS ma obiekty $ scope. Są to specjalne obiekty tworzone i obsługiwane przez AngularJS, w których przechowujesz swój model. Niektóre dyrektywy odradzają nowy zakres $, który domyślnie dziedziczy po zawinięciu zakresu $ przy użyciu prototypowego dziedziczenia JavaScript. Obiekt $ scope jest dostępny w kontrolerze i widoku.
To sprytna część. Ponieważ struktura dziedziczenia zakresu $ z grubsza odpowiada strukturze DOM, elementy mają dostęp do własnego zakresu, a wszelkie zawierające go zakresy płynnie, aż do globalnego zakresu $ (który nie jest taki sam jak zasięg globalny).
To znacznie ułatwia przekazywanie danych i przechowywanie danych na odpowiednim poziomie. Jeśli rozwijane jest rozwijane menu, tylko zakres rozwijany $ musi o tym wiedzieć. Jeśli użytkownik zaktualizuje swoje preferencje, możesz zaktualizować globalny zasięg $, a wszelkie zagnieżdżone zakresy nasłuchujące preferencji użytkownika zostaną automatycznie powiadomione.
Może się to wydawać skomplikowane, w rzeczywistości, kiedy się w niego zrelaksujesz, to jak latanie. Nie musisz tworzyć obiektu $ scope, AngularJS tworzy go i konfiguruje dla Ciebie, poprawnie i odpowiednio w oparciu o twoją hierarchię szablonów. Następnie AngularJS udostępnia go komponentowi za pomocą magii wstrzykiwania zależności (więcej na ten temat później).
Ręczne zmiany DOM a wiązanie danych
W jQuery ręcznie wprowadzasz wszystkie zmiany DOM. Konstruujesz nowe elementy DOM programowo. Jeśli masz tablicę JSON i chcesz umieścić ją w DOM, musisz napisać funkcję do wygenerowania HTML i wstawienia go.
W AngularJS możesz to również zrobić, ale zachęca się do korzystania z wiązania danych. Zmień model, a ponieważ DOM jest z nim powiązany za pomocą szablonu, DOM automatycznie się zaktualizuje, nie wymaga interwencji.
Ponieważ wiązanie danych odbywa się z szablonu, przy użyciu atrybutu lub składni nawiasów klamrowych, jest to bardzo łatwe. Jest z tym związany niewielki narzut kognitywny, więc cały czas to robisz.
<input ng-model="user.name" />
Wiąże element wejściowy z $scope.user.name
. Aktualizacja danych wejściowych spowoduje zaktualizowanie wartości w bieżącym zakresie i odwrotnie.
Również:
<p>
{{user.name}}
</p>
wyświetli nazwę użytkownika w akapicie. Jest to aktywne wiązanie, więc jeśli $scope.user.name
wartość zostanie zaktualizowana, szablon również się zaktualizuje.
Ajax cały czas
W jQuery wywołanie Ajax jest dość proste, ale wciąż możesz pomyśleć dwa razy. Jest dodatkowa złożoność do przemyślenia i spory kawałek skryptu do utrzymania.
W AngularJS Ajax jest Twoim domyślnym rozwiązaniem, które dzieje się przez cały czas, prawie bez zauważenia. Możesz dołączyć szablony z ng-include. Możesz zastosować szablon z najprostszą niestandardową dyrektywą. Możesz zawinąć wywołanie Ajax w usługę i stworzyć sobie usługę GitHub lub Flickr , do której możesz uzyskać dostęp z zadziwiającą łatwością.
Obiekty serwisowe a funkcje pomocnicze
W jQuery, jeśli chcemy wykonać małe zadanie niezwiązane z domem, takie jak pobieranie kanału z API, możemy napisać małą funkcję, aby to zrobić w naszym zamknięciu. To prawidłowe rozwiązanie, ale co, jeśli chcemy często uzyskiwać dostęp do tego kanału? Co jeśli chcemy ponownie użyć tego kodu w innej aplikacji?
AngularJS daje nam obiekty usługowe.
Usługi to proste obiekty zawierające funkcje i dane. Zawsze są singletonami, co oznacza, że nigdy nie może być więcej niż jeden z nich. Powiedzmy, że chcemy uzyskać dostęp do interfejsu API przepełnienia stosu, możemy napisać StackOverflowService
metodę definiującą metody.
Powiedzmy, że mamy wózek na zakupy. Możemy zdefiniować ShoppingCartService, który utrzymuje nasz koszyk i zawiera metody dodawania i usuwania przedmiotów. Ponieważ usługa jest singletonem i jest współdzielona przez wszystkie inne komponenty, każdy obiekt, który musi zapisać w koszyku i pobrać z niego dane. To zawsze ten sam wózek.
Obiekty usług są samodzielnymi komponentami AngularJS, które możemy wykorzystywać i wykorzystywać ponownie, gdy uznamy to za stosowne. Są to proste obiekty JSON zawierające funkcje i dane. Są one zawsze singletonami, więc jeśli przechowujesz dane w usłudze w jednym miejscu, możesz uzyskać te dane gdzie indziej, po prostu prosząc o tę samą usługę.
Iniekcja zależności (DI) vs. Instatiation - inaczej de-spaghettification
AngularJS zarządza twoimi zależnościami. Jeśli chcesz mieć obiekt, po prostu się do niego odszukaj, a AngularJS go dla ciebie dostanie.
Dopóki nie zaczniesz z tego korzystać, trudno jest wyjaśnić, jak wielki jest to dar czasu. W jQuery nie istnieje coś takiego jak AngularJS DI.
DI oznacza, że zamiast pisać aplikację i łączyć ją razem, zamiast tego definiujesz bibliotekę komponentów, z których każda jest identyfikowana przez ciąg znaków.
Powiedzmy, że mam komponent o nazwie „FlickrService”, który definiuje metody pobierania kanałów JSON z Flickr. Teraz, jeśli chcę napisać kontroler, który może uzyskać dostęp do Flickr, muszę tylko odwołać się do „FlickrService” według nazwy, kiedy deklaruję kontroler. AngularJS zajmie się utworzeniem instancji komponentu i udostępnieniem go mojemu kontrolerowi.
Na przykład tutaj definiuję usługę:
myApp.service('FlickrService', function() {
return {
getFeed: function() { // do something here }
}
});
Teraz, gdy chcę skorzystać z tej usługi, po prostu nazywam ją po imieniu w następujący sposób:
myApp.controller('myController', ['FlickrService', function(FlickrService) {
FlickrService.getFeed()
}]);
AngularJS rozpozna, że obiekt FlickrService jest potrzebny do utworzenia instancji kontrolera i dostarczy nam jeden.
To sprawia, że łączenie elementów jest bardzo łatwe i prawie całkowicie eliminuje tendencję do spagetyfikacji. Mamy płaską listę komponentów, a AngularJS przekazuje je nam jeden po drugim, kiedy i kiedy ich potrzebujemy.
Modułowa architektura usług
jQuery mówi niewiele o tym, jak powinieneś zorganizować swój kod. AngularJS ma opinie.
AngularJS daje moduły, w których możesz umieścić swój kod. Jeśli piszesz na przykład skrypt, który komunikuje się z Flickr, możesz utworzyć moduł Flickr, w którym będą zawijać wszystkie funkcje związane z Flickr. Moduły mogą zawierać inne moduły (DI). Główną aplikacją jest zwykle moduł, który powinien obejmować wszystkie pozostałe moduły, od których będzie zależeć twoja aplikacja.
Otrzymasz proste ponowne użycie kodu, jeśli chcesz napisać kolejną aplikację opartą na Flickr, możesz po prostu dołączyć moduł Flickr i voila, masz dostęp do wszystkich funkcji związanych z Flickr w nowej aplikacji.
Moduły zawierają komponenty AngularJS. Gdy dołączymy moduł, wszystkie komponenty w tym module stają się dla nas dostępne jako prosta lista identyfikowana przez ich unikalne ciągi . Następnie możemy wstrzyknąć sobie te komponenty za pomocą mechanizmu wstrzykiwania zależności AngularJS.
Podsumowując
AngularJS i jQuery nie są wrogami. Można bardzo ładnie używać jQuery w AngularJS. Jeśli dobrze używasz AngularJS (szablony, wiązanie danych, zakres $, dyrektywy itp.), Zauważysz, że potrzebujesz dużo mniej jQuery, niż mogłoby być wymagane.
Najważniejsze do zrozumienia jest to, że Twój szablon napędza twoją aplikację. Przestań próbować pisać duże wtyczki, które robią wszystko. Zamiast tego napisz małe dyrektywy, które wykonują jedną rzecz, a następnie napisz prosty szablon, aby je połączyć.
Nie myśl o dyskretnym JavaScript, a zamiast tego myśl o rozszerzeniach HTML.
Moja mała książka
Tak bardzo podekscytowałem się AngularJS, że napisałem o nim krótką książkę, którą z przyjemnością przeczytacie online http://nicholasjohnson.com/angular-book/ . Mam nadzieję, że to jest pomocne.