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.
Teraz pokażę Ci, jak możemy po
wywołaniu jakiegoś eventu uzyskać informacje na temat tego zdarzenia.
Więc mamy znowu trzy przyciski.
Zaczniemy od przypisania zdarzenia
kliknięcia do drugiego przycisku. Więc powiem btn2,
następnie addEventListener,
przypiszemy zdarzenie kliknięcia i tutaj podam funkcję.
Czyli już wiemy na tym etapie, że ta
funkcja się wykona kiedy klikniemy w przycisk drugi.
Ale co ciekawe można powiedzieć, że ten obiektowy model dokumentu podstawi nam
tutaj do tej funkcji automatycznie obiekt Event.
Skoro my tę funkcję tworzymy, to parametry tej funkcji możemy nazwać jak chcemy,
czyli możemy to nazwać e, możemy nazwać event,
to jest tylko parametr, który Ty tworzysz.
Niemniej jednak właśnie pod ten pierwszy
parametr zostanie podstawiony obiekt z eventem.
Ja sobie przyjąłem, że zazwyczaj tworzę to jako e.
Niektórzy piszą event po prostu albo evt, to zależy od Ciebie.
Nazwij to jak chcesz,
natomiast pod ten parametr zostanie podstawiony obiekt.
No i zróbmy sobie console.log tego
obiektu, żeby zobaczyć co nam tam przeglądarka podstawi.
Czyli klikam w ten przycisk, bo do tego to
przypisaliśmy i otrzymaliśmy coś takiego jak MouseEvent.
Co ciekawe te eventy mogą się od siebie różnić dlatego, że jak będziemy mieli
zdarzenia dotyczące klawiatury to tu może być KeyboardEvent itd.
Ale jest to jakiś obiekt,
czyli normalnie po kropce
tutaj po e kropka można się odwołać do jego
różnych metod i właściwości i zauważ, że on zawiera sporo tutaj różnych
właściwości, a także będą tutaj dostępne jakieś metody.
Czyli co my możemy tak naprawdę z tego eventu odczytać, no np.
w którym miejscu był kursor myszy, kiedy kliknęliśmy na ten element itd.
To co będziemy bardzo często odczytywać z takich eventów to jest target, czyli można
powiedzieć, że element, na którym wywołał się ten event.
I teraz tutaj jest jedna bardzo ciekawa rzecz, o której chcę wspomnieć.
Bo co chciałbym zrobić, jeżeli klikniemy na tym przycisk
wyobraźmy sobie, że po kliknięciu na ten przycisk z tej funkcji wysyłamy jakieś
zapytanie do serwera i chcemy ten przycisk zablokować.
Więc teoretycznie najprościej byłoby
powiedzieć skoro mamy w zmiennej już ten przycisk to btn2 i np.
set.Attribute disabled ustawimy na true. Ale
jeżeli chcemy się w bardziej dynamiczny sposób do tego odwołać, bo
powiedzmy ta funkcja będzie zdefiniowana w jakimś innym miejscu, potem będzie
zaimportowana i ta funkcja ona jakby w miejscu, w którym jest tworzona nie będzie
miała dostępu do takiej zmiennej to możemy to zrobić dynamiczniej i wewnątrz takiej
funkcji odwołać się do czegoś takiego jak event target.
Czyli można powiedzieć, że tym obiektem jak mamy tutaj ten event, to target będzie
nam kierował na element, na którym się wywołało to zdarzenie.
Czyli event.target daje nam dokładnie
takie samo odwołanie do tego przycisku jak pobranie go poprzez querySelector.
To jest dokładnie to samo.
OK, zobaczmy czy to zadziała.
Klikam na drugi przycisk
i jak widzisz został do niego dodany atrybut disabled.
Tutaj natomiast jest pewna pułapka, o której powiem teraz.
Zobacz mamy przycisk btn3.
Wygląda on niemal identycznie, ale w środku ma jeszcze element span i ten span
może być tutaj z powodów choćby dekoracyjnych.
Jeżeli teraz do tego trzeciego elementu,
do tego trzeciego przycisku przypiszemy dokładnie to samo, czyli po kliknięciu w ten
przycisk chcemy dodać do tego e.target atrybut disabled.
Zobaczmy co się stanie.
Klikam w trzeci przycisk
i nie został tutaj dodany ten atrybut.
Dlaczego?
Zobaczmy, bo ten atrybut został dodany do span.
Czyli to powinno Ci mówić o jednej bardzo ważnej rzeczy.
Chociaż przypisaliśmy zdarzenie kliknięcia do
przycisku, to pod event.target otrzymaliśmy span,
bo tak naprawdę kliknęliśmy na ten span, który jest wewnątrz.
Co zatem zrobić w sytuacji, w której nie chcielibyśmy otrzymać pod event.target
tego span, ale dokładnie element, na którym zarejestrowaliśmy zdarzenie
żeby mieć pewność, że event.target odwołuje się właśnie do tego przycisku.
Otóż mamy inną właściwość, która nazywa się currentTarget
i ja zawsze praktycznie z niej korzystam i pod nią zostanie zawsze podstawiony
element, na którym przypisałeś addEventListener.
Czyli tutaj nieważne, że wewnątrz przycisku kliknęliśmy w coś innego,
tutaj zawsze otrzymamy odwołanie do tego przycisku.
Więc jeżeli teraz sobie kliknę tutaj, to już jak widzimy wszystko działa i disabled
został dodany do tego konkretnego elementu.
Kiedy zatem korzystać z event.target a kiedy z currentTarget?
Wyobraź sobie taką sytuację, że na stronę doładowujemy dynamicznie jakiś kod HTML.
Nie będziemy tego teraz robić, ale chodzi
mi o to, że mamy tutaj taki przycisk, do którego nie przypisaliśmy żadnego zdarzenia.
Czyli można powiedzieć, że po kliknięciu w ten przycisk nic się kompletnie nie dzieje.
I co zrobić, jeżeli byśmy mieli więcej
takich elementów i nie chcemy do każdego z nich przypisywać takiego zdarzenia?
Oczywiście najlepiej jest to przypisać do każdego elementu np. w pętli, ale czasami jest
tak, że ajaxem wczytujemy więcej jakiś elementów, jakiegoś kodu HTML, a
mimo tego chcemy, żeby zarejestrowane wcześniej zdarzenia działały.
Czyli możemy zarejestrować zdarzenie
kliknięcia na ten przycisk tylko jeśli ten przycisk istnieje.
Ale możemy zrobić coś takiego, że
zarejestrujemy zdarzenie kliknięcia w dowolnym miejscu na body
i wtedy sprawdzimy czy kliknięty został przycisk czy nie.
Pokażę Ci jak to zrobić.
Odwołamy się do document.body.addEventListener i powiem, że po
kliknięciu na body, czyli w dowolnym miejscu i to jest tzw.
event delegation, to co robimy teraz.
Wywołaj mi taką funkcję.
Ale, że ja nie chcę wywoływać tej funkcji czy kodu, który tam zawrę
jeżeli gdziekolwiek kliknę, to możemy tutaj zrobić takiego if.
Jeżeli event.target
albo może go wyświetlmy, żebym Ci pokazał dokładnie o co chodzi.
event.target zobacz.
Czyli po kliknięciu w dowolne miejsce na body
mam event.target np. container.
Wtedy nic nie chcę robić, ale jeśli event.target
to będzie przycisk to wtedy chcę wywołać właśnie mój kod.
Czyli możemy sobie tutaj zrobić if i powiedzieć jeżeli event.target np.
ma klasę, czyli classList.contains,
jeżeli on ma klasę button to tylko wtedy wywołaj mój kod.
Czyli za każdym razem jak klikniemy
gdziekolwiek w body, w dowolny element, to ta funkcja się wykona, ale w środku możemy
ograniczyć jej kod do takiego if i wtedy wiemy, że jeżeli kliknęliśmy w przycisk to
tylko wtedy wykonamy kod, który tutaj podamy.
A więc możemy zrobić console.log Kliknąłeś przycisk.
Zobaczmy, teraz jak odświeżę
klikam sobie w body,
ta funkcja się wywołuje, ale warunek jest fałszywy.
Jeżeli kliknę w przycisk mamy kliknąłeś przycisk. Mimo tego, że do tego konkretnego
elementu nie przypisaliśmy bezpośrednio zdarzenia kliknięcia.
Tak jak wspomniałem, to będzie przydatne raczej w sytuacji, jeżeli wcześniej chcesz
zarejestrować takie zdarzenie, a potem będziesz np.
dynamicznie z serwera doczytywał jakiś kod HTML i sporo takich elementów zostanie
utworzonych, to po kliknięciu na te elementy zadziała to dokładnie tak samo,
bo zdarzenie zostało przypisane nie do tych elementów, ale do body i dopiero
wtedy jest sprawdzane czy targetem jest taki przycisk.
Na sam koniec pokażę Ci jeszcze jedną bardzo ważną rzecz, ale w tym celu
utworzymy sobie jeszcze jeden przycisk, więc może zróbmy sobie tutaj button 4 i
powiedzmy, że tutaj będzie is-warning, żeby on wyglądał troszkę inaczej.
OK i pobierzemy sobie go również tutaj.
Bo jeżeli chodzi o przekazywaną funkcję
tutaj ja utworzyłem funkcję w taki sposób, ale można utworzyć również funkcję
strzałkową, o czym chciałbym Ci powiedzieć.
Czyli zrobiłem btn4.addEventListener i po kliknięciu w ten przycisk najpierw
zrobię standardową funkcję i tutaj odwołamy się do eventu.
I chcę Ci pokazać, że wewnątrz takiej
funkcji po this masz dokładnie to samo co pod event.target,
ale nie do końca polecam korzystanie z tego this.
Zróbmy sobie console.log czy this to jest to samo co event.target?
Kliknijmy w ten czwarty przycisk i zobaczmy.
I jeszcze może dodamy sobie tutaj coś takiego.
OK.
Klikam i widzimy true.
To oznacza, że możesz teoretycznie zamiennie korzystać z this i z event.target
i często można to spotkać w różnych tutorialach, że zrobimy np.
this.setAttribute disabled.
Ale to po pierwsze będzie event.target, a nie event.currentTarget, a po drugie this
będzie działać tylko w tak stworzonej funkcji.
Gdybyś sobie tutaj podstawił funkcję strzałkową taką z ES6 zrobioną w ten sposób, to w
takiej funkcji this nie będzie już mogło być ustawione właśnie przez ten kod, który się
tutaj wykonuje i będzie kierować na coś zupełnie innego.
Zobaczmy. Kliknij mnie.
Teraz mamy false. I mógłbyś się zdziwić, że Ty wewnątrz takiej funkcji robisz sobie this
myśląc, że to jest to samo co event.target i np. przypisujesz taki atrybut disabled.
Natomiast tak nie jest.
Z tego powodu nie polecam skorzystania z
this w ogóle wewnątrz takiej funkcji obsługi zdarzenia,
natomiast jeżeli już byś to robił to pamiętaj, że jeżeli podstawiasz funkcję
strzałkową to wtedy to this nie będzie kierowało na to samo co event.target.