od Podstaw
9 godz. 20 min · JavaScript · Full-stack i Programowanie
Piotr PalarzWeb DeveloperJavaScript to język programowania, który napędza niemal wszystkie strony internetowe. Dopełnia on technologie HTML i CSS, za pomocą których tworzymy strukturę i wygląd dokumentu. Co jednak w sytuacji, gdy chcemy po kliknięciu w wybrany przycisk wyświetlić powiększone zdjęcie lub wczytać dodatkowe dane z serwera? To właśnie w takich sytuacjach przydaje się język JavaScript i tzw. DOM API, dostępne w przeglądarce. Jak się przekonasz, możliwości nowoczesnych przeglądarek w połączeniu z tym językiem są naprawdę ogromne.
Język JavaScript może być używany nie tylko na stronach internetowych. Z tego powodu, w kursie omówimy najpierw najważniejsze konstrukcje tego języka, które są niezależne od platformy uruchomieniowej. Dzięki temu zbudujesz fundamenty niezbędne do tego, by wykorzystać ten język np. w środowisku Node.js. Krok po kroku omówimy sposoby tworzenia zmiennych, dostępne typy danych i operatory. Następnie zobaczysz jak tworzyć tablice i obiekty, z jakich instrukcji warunkowych i pętli możesz korzystać, a także jak tworzyć własne funkcje. Przekazywana wiedza uwzględniać będzie nowości, które pojawiły się w języku wraz z rewolucyjnym standardem EcmaScript 6 (ES6).
Sam język JavaScript to nie wszystko, by tchnąć ducha w strony internetowe. Z tego powodu, przeglądarki internetowe udostępniają tzw. DOM API. To interfejs, który z użyciem języka JavaScript pozwala na manipulację treścią i wyglądem strony. W kursie bardzo dokładnie omówimy czym jest Obiektowy Model Dokumentu, a także jak z nim pracować. Zobaczysz jak tworzyć nowe elementy HTML i wstawiać je na stronę, jak modyfikować ich treść, atrybuty, style czy klasy CSS. Poznasz sposoby na odczytywanie położenia elementu na stronie i jego wymiarów, które będą niezbędne w wielu sytuacjach. Dowiesz się także, jak przypisywać obsługę zdarzeń w przeglądarce, by np. wywołać własną funkcję, gdy ktoś kliknie w wybrany przez Ciebie przycisk.
JSON to popularny format wymiany danych, a Ajax to potoczna nazwa dla asynchronicznych zapytań HTTP, które wysyłać możemy z poziomu kodu JavaScript. Dziś niemal każda strona internetowa wykorzystuje te technologie. W niektórych przypadkach jako dopełnienie podstawowej funkcjonalności witryny, a w innych jako główny motor napędzający stronę. Jeśli kiedykolwiek widziałeś, jak na stronie internetowej jakaś treść "doczytuje" się np. podczas przewijania - widziałeś w praktyce Ajax. W jednym z rozdziałów kursu zobaczysz, jak pracować z tym formatem, a także jak wysyłać wspomniane zapytania do serwera.
Choć kurs który masz przed sobą, jest kursem dla początkujących, to aby zrozumieć jak działa język JavaScript i jak z nim się współcześnie pracuje, omówimy dwa ważne tematy - zarządzanie zależnościami i bundlowanie kodu. Dowiesz się czym jest npm i jak z jego pomocą pobierać paczki gotowego kodu z internetu, a także jak sprawić, by bez trudnu dołączać je do własnego kodu. W tym celu skorzystamy z narzędzia snowpack, które pozwoli nam także na optymalizację kodu przed jego wypuszczeniem w świat. Na tym etapie omówimy również jak działają moduły ESM, pozwalające dzielić kod na mniejsze części.
Kurs podzielony został na możliwie krótkie lekcje, do których w każdej chwili możesz wrócić. Jeśli zatem zapomnisz jak odczytywać wymiary elementu na stronie, szybko odnajdziesz odpowiednią lekcję. Czym jednak była by sama teoria i proste przykłady, bez pokazania, jak połączyć je w całość i wykorzystać w praktyce? Dobra wiadomość jest taka, że w kursie stworzymy aż 5 praktycznych projektów, wykorzystujących zdobytą wcześniej wiedzę. Najpierw napiszemy program losujący Dużego Lotka, następnie dynamiczny pasek postępu przeczytania artykułu, dymek pojawiający się nad elementem po najechaniu na niego myszą, wygenerujemy tabelkę w użytkownikami na podstawie danych JSON, a na koniec tworzymy prosty odtwarzacz wideo, z możliwością pauzowania i przewijania filmu.
Kurs ten jest dla wszystkich osób, które znają już podstawy HTML i CSS i chciałyby przejść poziom wyżej i dodać do swoich stron dynamiczności. Żadna wcześniejsza wiedza z zakresu JavaScript nie jest wymagana, ale zalecana jest podstawowa wiedza z zakresu samego programowania (czym są zmienne, pętle, funkcje itd.). Materiał ten będzie również świetnym odświeżeniem i usystematyzowaniem wiedzy dla osób, które już z tym językiem miały do czynienia. Po przerobieniu tego kursu będziesz gotowy, by poznawać język JavaScript dalej i zacząć korzystać z nowoczesnych frameworków.
Stworzymy teraz kolejny praktyczny
projekt, a będzie to taka aplikacja, która pozwoli nam pobrać dane z serwera.
Będą to dane w postaci JSON i następnie
na ich podstawie wyrenderować taką tabelkę jak tutaj widzisz,
aczkolwiek ona będzie dłuższa. I serwer, którym się posłużymy to jest
ten, który już wcześniej widziałeś, czyli jsonplaceholder.
Natomiast tym razem nie korzystamy z posts ale z users. I zauważ, że to zwraca nam
taki JSON gdzie mamy tablicę z obiektami.
Każdy obiekt ma różne dane takie jak name, username, email,
następnie zagnieżdżony kolejny obiekt, gdzie
mamy street no i inne takie informacje adresowe.
My natomiast będziemy chcieli wykorzystać tylko te podstawowe jak właśnie name,
następnie nazwa użytkownika to było username i email.
Czyli taką tabelkę chcemy stworzyć.
I jej tutaj nie będzie, następnie klikniemy Pobierz dane,
dane się pobiorą i tabelkę wyrenderujemy.
Więc od czego zaczniemy?
Po pierwsze od tego, że będę chciał
przypisać zdarzenie kliknięcia do przycisku Pobierz dane.
Zatem ten przycisk już tutaj mam.
Przypisuje zdarzenie kliknięcia i funkcje
I w tej funkcji skorzystamy właśnie z
metody czy z funkcji fetch, którą już Ci pokazywałem.
Skopiuję sobie ten adres, bo to z niego
będziemy pobierać dane i wywołamy funkcję fetch przekazując właśnie ten adres.
Następnie zgodnie z tym co w dwóch
poprzednich lekcjach Ci pokazywałem będziemy chcieli tutaj zrobić then
i jak z serwera otrzymamy response to z tego response chcemy zwrócić json.
Czyli dzięki takiemu zapisowi w kolejnym
bloku then otrzymamy już konkretny json, a nie text, który się tutaj znajduje.
To jest tylko text, a json to będzie tablica z obiektami. Czyli za pomocą
JSON.parsed gdzieś pod spodem to zostanie odpowiednio zamienione.
I teraz co my chcemy zrobić w kolejnym bloku, kiedy już będziemy mieli dostęp do
tych użytkowników, napiszemy sobie tutaj data
i może na początek zróbmy console.log data,
żeby upewnić się, że wszystko jest tutaj pobierane poprawnie.
Klikam Pobierz dane
i rzeczywiście, jeżeli zerkniemy do panelu Network, wysłaliśmy zapytanie, ono jest w
tym miejscu i następnie zamieniliśmy to na JSON i mamy tutaj tych użytkowników.
Jest ich jak widzisz 10.
Z każdego z nich będziemy sobie mogli wyciągnąć te dane, które nas interesują.
Więc nie pozostało nic innego jak napisać
całą resztę kodu, ale nie w tej funkcji, tylko zrobimy do tego osobne funkcje.
A zatem to co będę chciał zrobić to w zasadzie tutaj od razu
jak otrzymam to data to będę chciał wywołać funkcję renderTable, którą za
moment stworzymy i przekaże jej tę tablicę z obiektami.
I tutaj możemy na tym zakończyć, a
wszystko zrobimy sobie właśnie w tej funkcji. Więc utworzymy funkcję renderTable,
wiemy, że pobieramy użytkowników, więc w
zasadzie możemy tutaj parametr nazwać users i to co będziemy chcieli zrobić to
oczywiście musimy sobie utworzyć taką
tabelkę jak tutaj widzisz. I można byłoby to zrobić na wiele sposobów.
Takim najbardziej skomplikowanym byłoby
tworzenie każdego elementu po kolei, czyli z użyciem documentCreateElement
gdybyśmy stworzyli table, potem
musielibyśmy stworzyć head i wstawić to do tego i poszczególne elementy.
Byłoby to niestety bardzo skomplikowane i
nie ma sensu tego robić, jeżeli możemy korzystać z metody innerHTML.
Zatem to co będę chciał zrobić, to będę
sobie chciał wszystko aż do tego momentu skopiować,
zobacz i będę chciał tutaj utworzyć taką stałą, którą nazwiemy table
i za pomocą Template Stringu po prostu wstawimy ten kod HTML w to miejsce.
Przeformatuje go tylko po to, żeby tutaj lepiej wyglądał i zakończymy
oczywiście to wszystko, tbody musimy
zakończyć i następnie zakończyli byśmy samo table. Tak by to wyglądało.
I mamy już jakiś fragment tej tabelki i
następnie będziemy chcieli ją wstawić na stronę.
Żeby to zrobić to tabelkę, którą tutaj mieliśmy już od początku.
Ja ją tutaj mogę zwinąć i wykomentować, żeby ona ze strony zniknęła.
I teraz pokażę Ci, w jaki sposób możemy z
użyciem innerHTML ten kod wstawić na stronę.
Zauważ, że nie musieliśmy tworzyć każdego elementu z osobna, ale jest jeden element,
który musimy utworzyć i będzie to jakiś taki pusty div.
Więc stałą nazywam div i za pomocą document.createElement
utworzę element div i następnie do tego div za pomocą innerHTML
przypisze cały ten kod tabelki, który mamy wyżej.
Dzięki temu przeglądarka utworzy wszystkie te elementy. Więc nie pozostało nic innego
jak ten element div wstawić na stronę w to miejsce, gdzie mieliśmy tę tabelkę,
a więc tak naprawdę wstrzyknąć go do tego elementu container.
OK, czyli możemy wyszukać sobie na stronie tego elementu container za pomocą
document.querySelector container po klasie i zrobimy mu append div.
OK.
To sprawi, że ta tabelka zacznie się tutaj pojawiać.
Oczywiście ona jeszcze nie jest kompletna,
ale jak widzisz w ten sposób mogliśmy ten problem rozwiązać.
No i teraz w zasadzie pozostała jedna bardzo istotna rzecz.
Otóż tutaj wewnątrz tego tbody będziemy chcieli utworzyć tr dla każdego elementu.
No i generalnie dokładnie to samo co mieliśmy tutaj. Czyli dla każdego
użytkownika takie tr i takie td będziemy chcieli utworzyć.
Znowu nie będziemy ich tworzyć za pomocą document.createElement
tylko znowu w formie stringu, który tam wstrzykniemy z użyciem innerHTML.
Natomiast jak zrobić tak, żeby tutaj można
było podstawić od razu jakby gotowy kod HTML
dla wszystkich użytkowników, którzy zostali tutaj przekazanie z tego JSON.
Otóż możemy sobie tutaj zinterpolować wywołanie funkcji, którą nazwiemy renderRows,
czyli wyrenderuj wiersze i jej przekażemy tych użytkowników.
Ta funkcja musi zadbać o to, żeby dla każdego elementu tablicy, który tam będzie
zwrócić nam taki oto string z odpowiednimi danymi.
Więc stwórzmy sobie teraz tą funkcję, którą nazwiemy renderRows.
Ona otrzyma właśnie tych użytkowników, więc parametr nazwiemy users, chociaż
to users i to users jak widzisz nazywa się tak samo, ale w dwóch różnych funkcjach,
więc one w żaden sposób ze sobą nie kolidują.
Tutaj to users przekazujemy oczywiście
i tutaj mamy do tego dostęp.
No i teraz najważniejsze pytanie w jaki
sposób możemy najłatwiej wygenerować dla wszystkich elementów tablicy users?
Bo jest to tablica, w której mamy poszczególne obiekty
i jak możemy dla wszystkich tych elementów
wygenerować taki tr o jakim mówiłem, czyli coś takiego.
W zasadzie możemy sobie to też skopiować.
Możemy skorzystać z metody map, która jest dostępna na tablicach i ta metoda wywoła
funkcję, którą podamy dla każdego elementu tablicy.
I to, co z tej funkcji zwrócimy znajdzie się pod danym indeksem tablicy.
Czyli jak mielibyśmy tablicę 1, 2, 3 na niej wywołali map i przekazali tam funkcję,
otrzymalibyśmy tam elem,
to to co zwrócimy z tej funkcji np.
elem razy 10 powiedzmy znajdzie się w nowej tablicy i w ten
sposób utworzylibyśmy nową tablicę, gdzie mielibyśmy 10, 20, 30.
Mam nadzieję, że to jest jasne.
W razie czego zapauzuj i zobacz co tutaj się dzieje.
Czyli otrzymujemy jeden element i to co
zwrócimy znajdzie się pod tym indeksem w nowej tablicy.
Skoro my tutaj otrzymamy
jednego takiego użytkownika możemy sobie
zobaczyć jeszcze raz co nam się tam pobiera z serwera,
tutaj w preview, będzie to taki oto obiekt to możemy z niego zwrócić właśnie string
w postaci takiego wiersza, który skopiowałem.
Czyli tak to wygląda.
Zatem najpierw odwołamy się do users.map i tutaj przekażę funkcję.
Może to być funkcja taka strzałkowa.
W ten sposób. Więc pod user będziemy mieli za każdą
iteracją, bo to map się wykonuje w pętli za każdą iteracją jeden taki obiekt i stąd
będziemy chcieli zwrócić taki Template String, który trochę lepiej sformatuje, w
ten sposób i tutaj będziemy chcieli podstawić,
zobaczmy, id użytkownika, potem name, username i email.
Z tych pól sobie skorzystamy.
A zatem za pomocą interpolacji
jeżeli pod user mamy jeden taki obiekt z JSON utworzony to możemy się odwołać
tutaj to user.id,
następnie do i user.name,
następnie będzie to user chyba username. Zobaczmy.
Zgadza się
i chcę taki utworzyć link po kliknięciu w który można otworzyć od razu maila
więc tutaj chcemy podstawić ten mail i również tutaj.
A zatem robię taką interpolację w dwóch miejscach i piszę user.email
I to oznacza, że cały ten zapis stworzy nową tablicę, gdzie pod każdym indeksem
będzie po prostu taki string z uzupełnionym danymi.
A więc zamieniliśmy tablicę users na kolejną tablicę, która korzysta z tych
danych, ale będzie to już tablica po prostu z ciągami znaków.
To oznacza tylko tyle, że wystarczy tę tablicę zwrócić.
Natomiast tutaj będzie jeszcze jeden problem.
Zobaczmy.
Zobacz. Pobierz dane i zobacz, tu jakieś dziwne rzeczy nam się wstawiły.
Zobaczmy, co to w ogóle jest.
Jakiś div się tutaj pojawił z jakimiś dziwnymi przecinkami, potem jakaś tabelka.
No właśnie przeglądarka była w stanie
jakby wygenerować tę tabelkę, ale tak naprawdę popełniliśmy tutaj taki błąd, że
zwracamy tablicę i w tym miejscu podstawiamy tą tablicę,
więc domyślnie na niej zostało zrobione
toString, gdzie wszystkie elementy zostały oddzielone przecinkami.
Przeglądarka sobie te przecinki wyciągnęła w inne miejsce i poprawnie wyrenderowała
tablicę, ale tak naprawdę to co chcieliśmy tutaj zrobić z tej funkcji render Rows,
czyli w tym miejscu to nie zwrócić tablicy, ale zwrócić string.
Skoro metoda map tworzy nam nową tablicę i pod każdym indeksem znajduje się taki
string, to chciałbym na końcu całą tę tablicę metodą join
po prostu połączyć i możemy ją połączyć na pustym ciągu znaków albo na nowym wierszu.
To nie ma większego znaczenia.
Natomiast dzięki join sprawimy, że renderRows
nie zwraca już tablicy, ale string, gdzie będą połączone wszystkie elementy
tablicy. I ten string zostanie zinterpolowany w tym miejscu.
Więc jak to zapiszę, zobaczmy.
Teraz już wszystko jest w porządku.
No i w taki sposób udało nam się stworzyć taką funkcję
czy w zasadzie dwie funkcje, które
renderują nam tabelkę na podstawie danych z serwera.
I gdybym w dowolnym momencie chciał tutaj dodać kolejne dane.
Zerkam sobie do JSON, który jest zwracany np.
phone,
no i wtedy mogę dodać taką kolumnę w tym miejscu.
Tutaj dodałbym telefon, a tu gdzie renderuje wiersz,
w td dodałbym sobie właśnie odwołanie do user.phon
no i mielibyśmy kolejną kolumnę załatwioną.
Ostatnią rzeczą, którą możemy zrobić na
koniec, to kiedy pobierzemy te dane to możemy ukryć ten przycisk, bo jak jeszcze
raz klikniemy to ta tabelka będzie wstawiona po raz kolejny.
To można zrobić w dowolnym miejscu.
Możemy to zrobić np.
tutaj w kolejnym bloku then, który się wykona
po tym bloku, możemy po prostu wstawić taką
funkcję sztrzałkową, odwołać się do button i wywołać na nim remove.
Czyli to można zrobić tu, ale równie
dobrze można to zrobić w metodzie renderTable,
chociaż chciałem, żeby ona była trochę jakby samodzielna i nie musiała nic
wiedzieć na temat tego przycisku, stąd ten przycisk ukrywam
w tym miejscu. Pobieramy dane, ukrywamy
przycisk czy w zasadzie usuwamy go ze strony i dane są wyświetlone w ten sposób.
Jak zatem widzisz w tzw.
czystym JavaScript
w ten sposób można wyrenderować dane, JSON na stronie,
natomiast jeżeli w przyszłości będziesz
korzystał z frameworków typu View, React czy Angular, tam będzie to można zrobić w
nieco bardziej przejrzysty i prostszy sposób,
ale warto wiedzieć, że gdybyśmy tylko dla tego celu chcieli dołączyć do strony taki
framework, to dodajemy od kilkudziesięciu do nawet kilkuset kilobajtów dodatkowego
kodu, bo tyle te frameworki zajmują tylko po to, żeby nam się pracowało wygodniej.
Więc jeżeli masz pobrać jakieś dane z
serwera i w jakiś sposób je wyświetlić i nie potrzebujesz tego robić na wielu
podstronach czy w wielu miejscach, spokojnie możesz to zrobić w tak zwanym
czystym JavaScripcie, tak jak Ci teraz pokazałem.
No i jak widzisz również nie musimy za
każdym razem tworzyć wszystkich elementów z użyciem createElement.
Możemy utworzyć string gdzie będzie kod HTML.
Następnie ten HTML ustawić poprzez innerHTML
i dopiero wtedy taki element wstrzyknąć na stronę.