Techniki Zaawansowane
5 godz. 11 min · Vue.js · Full-stack i Programowanie
Piotr PalarzWeb DeveloperKurs, który masz przed sobą, to kontynuacja wydanego wcześniej kursu Vue.js od Podstaw. W pierwszym kursie omówione zostały najważniejsze koncepcje pracy z Vue, a w tym materiale poruszamy już bardziej zaawansowane tematy. Przede wszystkim skupimy się na pracy z użyciem nowoczesnego workflow, co da nam niezwykłą swobodę tworzenia aplikacji internetowych. Jeśli zatem znasz już podstawy pracy z tym frameworkiem i chcesz wskoczyć na kolejny poziom wtajemniczenia, ten kurs jest zdecydowanie dla Ciebie. A co znajdziesz w materiale?
Na początku zobaczysz, jak szybko tworzyć pliki startowe do nowej aplikacji z użyciem narzędzia vue-cli. Omówimy możliwość dzielenia kodu na wiele plików, tworzenia szablonów, a także wykorzystywania bezpośrednio funkcji renderującej, do której zamieniane są na etapie builda wszystkie szablony.Zobaczysz również czym są i jak pracować z komponentami funkcyjnymi i tzw. mixinami, które pozwolą reużywać raz napisany fragment kodu.
Przepływ informacji to bardzo ważny temat w każdej aplikacji internetowej. Vue oferuje kilka sposobów na to, aby komponenty mogły się ze sobą komunikować. Ich omówienie zaczniemy od najprostszych technik, które świetnie sprawdzają się w wielu przypadkach. Następnie rozszerzymy możliwości instancji Vue w ten sposób, aby wszystkie komponenty miały dostęp do scentralizowanego miejsca, gdzie przechowywany będzie stan aplikacji.Tam jednak, gdzie aplikacja wymaga zarządzania większą ilością danych jednocześnie, powyższe techniki mogą być niewystarczające. Z tego powodu, podobnie jak w innych frameworkach, Vue posiada oficjalny wzorzec oraz bibliotekę do zarządzania stanem aplikacji. Rozwiązanie to nazywa się VueX i w kursie zostanie ono dokładnie omówione. Zobaczysz zatem jak skonfigurować tzw. store, jak przechowywać w nim dane, jak je wyświetlać w widokach, aktualizować za pomocą tzw. mutacji czy pracować z nimi wykorzystując akcje. Przekonasz się, że początkowa większa ilość pracy, aby wszystko skonfigurować, w pewnym momencie zaczyna się opłacać.
Tworzenie nowoczesnych aplikacji typu SPA (Single Page Application) nie może się obejść bez zmian widoków. Dobrą praktyką jest, aby wraz z takimi zmianami, aktualizowany był również pasek adresu. Wykonanie takiego zadania umożliwiają nam tzw. routery. Vue posiada oficjalny dodatek o nazwie vue-router, który w tym kursie dokładnie omówimy.Zobaczysz jak dołączyć router do swojego projektu, a także jak konfigurować ścieżki. Poruszymy tematy takie jak generowanie odnośników, dynamiczne parametry, tworzenie zagnieżdżonych ścieżek czy nawigacja z poziomu kodu JavaScript. Dowiesz się również, jak tworzyć tzw. guardy, które umożliwią lub zablokują możliwość wyświetlania wybranego widoku, np. w zależności od tego czy użytkownik jest aktualnie zalogowany.
Trzecim, po zarządzaniu stanem aplikacji i wykorzystaniu routingu, komponentem, który niezbędny jest do tworzenia aplikacji napędzanych danymi, jest możliwość wysyłania zapytań HTTP.Tę czynność umożliwi nam bardzo popularna, acz niezależna od Vue biblioteka axios. Zobaczysz jak za jej pomocą pobierać i wysyłać dane. Aby jednak jak najwygodniej pracować z tym rozwiązaniem, połączymy axios z Vue, udostępniając tak naprawdę jej metody wewnątrz każdego komponentu.
W jednym z rozdziałów kursu podejmiemy temat walidacji formularzy. Zobaczysz jak z pomocą popularnego pluginu dla Vue, robić to w bardzo prosty sposób.Omówimy różne funkcje walidujące, które umożliwią sprawdzenie poprawności pól tekstowych, radio czy checkboxów. Zobaczysz jak w łatwy sposób wyświetlać komunikaty o błędach i warunkowo zmieniać wygląd pól. Nie zabraknie również informacji o asynchronicznej walidacji, która pozwoli nam na żywo sprawdzać czy wpisany adres email jest dostępny czy też nie.
Kurs ten oczywiście to nie tylko niezbędna teoria, ale także praktyczne przykłady. Aby jak najlepiej poznać omawiane techniki, wykorzystamy je do stworzenia ciekawych aplikacji.Pierwszą z nich będzie konfigurator produktu, który umożliwi użytkownikowi wybór podzespołów zamawianego komputera. Każdy taki wybór będzie wpływał na końcową cenę, która będzie na bieżąco aktualizowana. Po wybraniu wszystkich opcji, dane prześlemy na serwer. To projekt który pokaże Ci jak przechowywać dane z użyciem VueX, a także jak na ich podstawie wyświetlić widok i napisać logikę.Innym projektem, który wykonamy, będzie Quiz. To aplikacja, gdzie użytkownik odpowiadał będzie na serię pytań pobranych z serwera, a do wyboru będą 3 odpowiedzi. Po przejściu przez wszystkie pytania, wyślemy do serwera zapytanie, a ten w zamian zwróci nam listę poprawnych odpowiedzi. Dzięki temu pokażemy użytkownikowi, gdzie miał rację, a gdzie popełnił błąd. Aplikacja ta wykorzystywać będzie wszystkie najważniejsze techniki, tj. VueX, routing, a także Ajax.
Kurs ten jest dla wszystkich osób, które czują się już swobodnie w pracy z frameworkiem Vue. Jeśli zatem masz już solidną wiedzę podstawową lub przerobiłeś kurs Vue.js od Podstaw, to zdecydowanie jesteś gotów na poszerzenie swoich umiejętnośći w pracy z tym frameworkiem. Co ważne, doświadczenie w pracy z innymi frameworkami JavaScript nie jest tutaj wymagane, a jedyne co będzie bardzo pomocne, to znajomość nowej składni EcmaScript 6.
Vue.js 2.x.x
OK.
Kontynuujemy prace nad naszym konfiguratorem produktu, więc spróbujmy napisać trochę logiki.
Chciałbym zrobić rzecz następującą. Jeżeli tutaj, gdzie generujemy sobie product options, czyli tutaj. Przypiszemy
zdarzenie kliknięcia, do elementu, który jest wewnątrz, to chciałbym to zrobić, to chciałbym móc go zaznaczyć
w Vuex storze. Chciałbym tutaj przypisać zdarzenie click, kiedy ktoś kliknie na ten element, to chciałbym wykonać metodę,
którą nazwiemy tutaj select i do niej przekażemy ten jeden wybrany obszar, więc ta metoda musi istnieć
tutaj wewnątrz komponentu ProductOptionGroup.
Dlatego stwórzmy sobie teraz tutaj,
select i ona otrzyma option.
OK i na jej podstawie będziemy chcieli zacomit'ować sobie za moment mutacje, ale zróbmy najpierw
console.log select i zobaczmy, czy to w ogóle nam zadziała. Czy w momencie, jak klikamy na któryś przycisk,
powinno się coś wydarzyć.
Tak się jednak nie dzieje i tutaj musimy zastosować pewien trik, bo jeżeli przypisuje kliknięcie do elementu
option, a wiemy, że on docelowo jest zamieniony na button, który znajduje się tutaj w templatce, to ten button
nie jest klikamy,
czyli jakby to zdarzenie kliknięcia do niego nie przechodzi.
Ale jeżeli tutaj w tej opcji dodamy sobie modyfikator, który się nazywa native, to wtedy kliknięcie zostanie
przypisane do pierwszego elementu,
tutaj właśnie z templatki, bo tu zawsze musi być jeden element, czyli teraz jeżeli odświeżę i kliknę, widzimy
w konsoli, że wszystko jest w porządku i jeden wybrany option powinien tam być przekazywany.
Pamiętaj ciągle z tego json'a,
czym jest taki option.
Otóż jest to taki oto obiekt, więc będziemy mieli jego code.
Kiedy mamy dostęp również do feature, to będziemy mogli w tym globalnym storze napisać sobie feature, na przykład
procesor i do tego przypisać wybrany kod, memory
i znowu wybrany code.
Dlatego właśnie będziemy chcieli stworzyć mutację i tutaj ją zacommit'ować,
czyli chciałbym tutaj napisać this store commit i mutacje nazwiemy też select, aczkolwiek pamiętaj,
te nazwy tutaj nie muszą być takie same i tam będę chciał przekazać ten payload, tak zwany, które robiliśmy
w tym kursie i chciałem powiedzieć, że pierwsza rzecz to feature i tutaj mam dostęp do this feature, bo
jest przekazana jako prop i właśnie to feature,
to będzie taki jeden obiekt, więc będę miał dostęp do jego code.
Za moment, dokładnie tutaj będę chciał to przekazać, a druga rzecz, jaką chcę w tym paylodzie wysłać, to jest
option i tutaj będę miał o dostęp do option, właśnie z tego parametru tutaj, przekazanego po kliknięciu,
option code, czyli tak jak mówiłem, wyślemy sobie coś takiego jak np. procesor i 725. To przekażemy do
tej mutacji, natomiast musimy teraz na naszym storze taką mutację utworzyć.
Więc przejdźmy tutaj i stwórzmy taką mutację, która będzie przyjmowała tutaj odpowiednie parametry. Nazwiemy
ją select, tak jak tam zrobiliśmy commit. Ona przyjmuje
być może pamiętasz, state i payload i ona może bezpośrednio modyfikować state, więc będę chciał sobie tam
coś dodać.
Z tym, że jeżeli pod state i zerkniemy tam sobie, pod state selected mamy taki obiekt, to wydawałoby
się że wystarczy napisać state.selected.
I tutaj moglibyśmy coś dodać.
Czyli mając feature pod payload.feature,
podamy tutaj np. procesor i piszemy
payload.option i wydawałoby się, że będzie wszystko w porządku.
Natomiast, niestety nie będzie to działać reaktywnie, ale zobacz, że w ogóle zacznie działać. Jeżeli przejdziemy
do Vuex'a tutaj. Mamy w selected jako pusty obiekt. Jeżeli coś zaznaczę, pojawia się tutaj processor i7.
Tylko, że za chwilę, kiedy będziemy chcieli z tego korzystać, nie będzie to działać reaktywnie.
Gdyby to była tablica i wykonali byśmy do niej push, to Vue opakowuje sobie metody tablic i to zadziałałoby poprawnie.
Natomiast z uwagi na to, że jest to obiekt, to Vue nie może wykryć, że my tutaj coś daliśmy.
Z tego powodu powinniśmy to dodawać za pomocą metody Vue.
I muszę sobie taki Vue tutaj zaimportować i tutaj napiszemy coś takiego, Vue.set.
Mówimy, na którym obiekcie chcemy ustawić reaktywne właściwości, na state i następnie selected, co chcemy
ustawić, czyli jaki ma być klucz - payload.
Tak jak mieliśmy wcześniej i jaka ma być jego wartość,
payload.option. To jest jedyny sposób, który nam gwarantuje, że dodanie do tego obiektu selected, jakiegoś
klucza i wartości sprawi, że to będzie działać w sposób reaktywny.
I tyle wystarczy, żeby zacommit'ować sobie taką mutację. Teraz po odświeżeniu znowu nic tutaj nie ma.
Wybieram jakąś wartość i ona się tutaj pojawia.
Natomiast teraz będzie działać reaktywnie i będziemy za chwilę mogli się do tego odwołać, żeby zaznaczyć
sobie np. ten przycisk. OK.
Jak zatem moglibyśmy stwierdzić, czy ten przycisk jest zaznaczony czy nie. Przejdziemy do product.option
tutaj i chciałbym tutaj bindować klasę do tego elementu.
I ta klasa to będzie btn-primary i ona będzie wtedy dodawana.
Jeżeli ten element jest zaznaczony, czyli selected.
No właśnie, skąd możemy to sprawdzić.
Otóż dodamy tutaj taką computed property,
selected i mając tutaj dostęp do feature, które w poprzedniej lekcji przekazaliśmy, to możemy np. odczytać
coś takiego jak processor mając dostęp do naszej opcji, możemy odczytać jej kod, to możemy sprawdzić czy
w tym naszym Vuex storze znajduje się processor i jest równy takiej i takiej wartości.
Jeżeli tak, to wtedy ta opcja powinna być zaznaczona.
Natomiast musimy to zrobić z użyciem gettera. Z tej naszej funkcji
będę chciał zwrócić coś takiego,
return this store getters i chciałbym, żeby ten getter był funkcją, która będzie przyjmowała właśnie feature i option,
więc przekażemy jej this.feature.code i następnie this.option.code, czyli tak jak mówiłem np. processor
i7. Przekażemy coś takiego, do tego gettera, więc teraz przejdźmy do getterów i musimy sobie taki getter utworzyć,
selected. On tutaj otrzymuje state. Natomiast my ten getter jakby wywołaliśmy, a to oznacza, że tak naprawdę z
niego musimy zwrócić funkcje i to ta funkcja będzie przyjmować parametry, które tutaj przekazaliśmy, czyli
feature i następnie option.
Ok.
No i teraz na jej podstawie będziemy mogli sprawdzić czy w state, return state.selected, czyli ten nasz
obiekt.
Czy on ma w sobie feature i czy ona ma dokładnie taką wartość jak option.
Jeżeli tak, to zwrócimy tutaj true.
I tutaj musimy jeszcze zrobić funkcję strzałkową.
Teraz powinno być już w porządku.
Zobaczmy zatem, czy to ma sens.
Widzimy, że jakieś błędy się tutaj pojawiły.
Odświeżmy raz jeszcze, ale widzimy, że this store getters is not a function. Chyba zabrakło tutaj jeszcze czegoś,
zapewne ty to zauważyłeś, getters i oczywiście tutaj musimy napisać selected.
OK, teraz powinna to być funkcja, powinno działać, jeśli zaznaczę jakiś element, zobacz, że automatycznie
reaktywnie to działa, bo po pierwsze zmieniliśmy to tutaj w Vuex storze, czyli w tym miejscu to się zmieniło, a
po drugie zostało odpowiednio odzwierciedlone.
I jak widzisz, tutaj w tym to Vuex storze możemy zmieniać te wartości, zawsze tylko jedna jest zaznaczona i wygląda
na to, że wszystko tutaj działa poprawnie. Teraz jeszcze mamy jeden problem, mianowicie cenę. Tutaj trzeba
będzie troszeczkę po główkować, ale ja pokażę ci gotowe rozwiązanie, postaram się je wytłumaczyć.
Chciałbym stworzyć getter, który nam tą cenę będzie w lepszy sposób liczył, bo on teraz zwraca cenę
z tego produktu, czyli tą która znajduje się w tym miejscu.
Cenę bazową, a ja chciałbym po zaznaczeniu jakiejś opcji wziąć sobie jej cenę i do tej ceny bazowej jeszcze
dodawać, czyli wziąć wszystkie zaznaczone opcje, które są aktualnie i ich dodatkowe ceny doliczyć i będziemy
musieli sobie ten getter troszeczkę zmodyfikować ja tutaj może wkleję gotowy kod i postaram Ci się
go wytłumaczyć. Troszeczkę tego jest, ale nie martw się, tu jeszcze będziemy musieli na górze zaimportować
bibliotekę lodash, którą też mamy zainstalowaną, bo ona nam po prostu tutaj życie ułatwi.
Na początku chcę się odwołać do state.product.features, czyli tutaj pod featureschcę zapisać dokładnie tę tablicę, którą mamy
w takim json'ie, całą tę tablicę.
Ok.
Następnie chce utworzyć zmienną sum, którą na końcu do tej bazowej ceny produktu będziemy dodawać i teraz
chce przeiterować przez wszystkie klucze w state selected i zauważ, że jeżeli tutaj mamy zaznaczone trzy rzeczy,
to będę chciał przeiterować przez ten wiersz, ten wiersz i ten wiersz, OK, mamy to tutaj i za pomocą metody
find
będę chciał w features,
Czyli w tym właśnie produkcie, znaleźć taki element który ma code o wartości key, czyli dla nas tutaj kluczem
będzie np. drive.
Ja w tym momencie, jak widzisz, chcę znaleźć element w tym jason'ie, feature, który również ma code drive i
cały ten obiekt zostanie dla mnie zwrócony. Teraz będę chciał przeiterować sobie przez jego opcje i znaleźć
taką opcję, którą mamy aktualnie zaznaczoną,
czyli mamy zaznaczone drive ssd-512.
Więc ja chcę znaleźć obiekt który ma tutaj code 512 i dopiero wtedy zwrócić jego cenę.
To robię tutaj, wyszukuje już w tym znalezionym feature.option takiego, który ma code w naszym przypadku
to ssd 512,
dla przykładu. Kiedy już to mam to z tej opcji dodaje sobie są cenę i tak samo przelecimy sobie przez pozostałe,
czyli np. processor i drive, wszystkie, które są zaznaczone. Skumuluje ich cenę
tutaj, do tej zmiennej sum i na końcu ją zwrócimy, więc może się to wydawać skomplikowane, ale kiedy to
się pisze krok po kroku, to ma to jak najbardziej sens.
Teraz mamy cenę taką. Jeżeli zaznaczę coś droższego,
jak widzisz cena się aktualizuje. Jeżeli wrócę do pierwotnej postaci,
cena znowu wraca do takiej samej postaci.
OK, teraz chciałbym jeszcze zrobić taką rzecz, że na samym początku, żeby były zaznaczone wszystkie te
domyślne parametry, czyli te które tutaj w tym sezonie mają cenę 0. Price 0, price 0, czyli taką, która nie dodaje do
ceny,
znaczy, że jest to domyślnie w tej podstawowej cenie, to chciałbym każdy z tych elementów zaznaczyć. To
będziemy mogli zrobić tutaj w bardzo łatwy sposób.
W ProductOptionGroup, w tym miejscu gdzie robiliśmy metodę select. Będę chciał po utworzeniu takiego komponentu,
czyli np. w tym hook'u created,
znaleźć sobie wszystkie options, które tutaj mamy, które mają cenę o i po prostu je odfiltrować,
czyli mamy tutaj feature i options następnie. Pamiętaj, że feature to będzie taka pojedyncza cecha i chce przeiterować
przez jej opcje, więc zróbmy sobie to w tym miejscu,
this.features, następnie metoda filter. Tutaj otrzymam jedną opcję, tutaj feature.option oczywiście, filter i będę
chciał sobie stąd zwrócić tylko takie, które mają price równą 0. Kiedy sobie to już zwrócę to zwraca
mi nową tablicę i po tej tablicy przeiteruję metodą forEach.
I tutaj również będę miał jeden option i każdy z nich będę chciał zaznaczyć naszą metodą, którą mamy
wyżej czyli this.select i przekaże tam ten option.
Powinno nam to zadziałać, sprawdźmy po odświeżeniu. Okazuje się, że jak najbardziej, no i kiedy je zaznaczamy
to wykonuje się mutacja, a więc również uzupełniany jest nasz store.
Jak widzisz wszystko to fajnie już dynamicznie działa i w zasadzie pozostało nam zrobić ostatnią rzecz,
już tutaj.
A ona polega na tym, że po kliknięciu w ten przycisk chciałbym wysłać zapytanie do serwera, więc ten przycisk
mamy tutaj jeżeli byśmy sobie przeszli do product, na dole.
Złóż zamówienie, przypiszę do niego zdarzenie kliknięcia i napiszemy order.
Oczywiście taką metodę teraz musimy sobie tutaj utworzyć,
order i chciałbym w niej, po prostu, puścić akcję, czyli o akcjach w Vuex'ie już uczyliśmy, więc zrobimy
this store i akcję robimy za pomocą dispatch.
Akcja się będzie nazywała order i to w zasadzie tyle, co jest nam tutaj potrzebne.
I teraz przejdźmy na koniec jeszcze do actions
i taką akcję będziemy chcieli dodać, order.
Wiemy, że akcja tutaj otrzymuje state i commit, czyli możemy sobie to z destrukturyzować w taki oto
sposób i mógłbym tutaj jeszcze zaimportować sobie
axios, import axios from
axios.
Będziemy mogli wysłać takie zapytanie i pamiętaj, że axios musi commit'ować mutacje, czyli będziemy musieli
za moment mieć jakąś mutację i ja może tutaj wkleję już ten kod, bo on jest bardzo prosty, czyli będziemy
chcieli wysłać pod adres localhost:3000/order state selected, czyli to wszystko co do tej pory
zaznaczyliśmy w formie json'a,
axios zadba o to, żeby poprawnie to wysłać na serwer.
Kiedy serwer zwróci nam poprawną odpowiedź, to chcemy wykonać commit finish.
Pamiętasz, że akcje mogą być asynchroniczne, natomiast wszystkie mutacje muszą być synchroniczne, dlatego
tutaj wykonujemy mutacje i taką mutacje musimy jeszcze dodać.
Ona będzie bardzo prosta, dlatego również wkleję fragment kodu i w razie czego, po prostu, sobie ją przepisz.
Ta mutacja wygląda tak, że po prostu state finish ustawia na true.
Dzięki temu, że tutaj będzie true, to w produkcie nie będziemy pokazywać już całego produktu, tylko pokażemy komunikat,
który jest na dole.
Więc zobaczmy raz jeszcze, zaznaczamy jakieś produkty.
Złóż zamówienie, serwer nam odesłał odpowiedź i wszystko jest OK.
Tą odpowiedź byśmy mogli zobaczyć.
Ok, wiem że w szybkim tempie bardzo robiliśmy ten projekt.
Natomiast jeżeli sobie pauzowałeś i wpisałeś, to wierzę że wszystko dobrze zrozumiałeś.
Mam nadzieję, że widzisz jak Vue pomaga ci tworzyć naprawdę ciekawe aplikacje.
Oczywiście zawsze coś można zrobić jeszcze lepiej, ale myślę, że całkiem nieźle ta aplikacja tak czy siak
jest stworzona. Także to jeszcze nie wszystko w tym kursie, ale mam nadzieję, że ten projekt mimo wszystko
również ci się podobał.