Czym jest Alpine.js? - icomMedia

Czym jest Alpine.js?

Czym jest Alpine.js?

Alpine.js to lekka biblioteka JavaScript, która umożliwia nadawanie stronom www interaktywności bez ciężkiego procesu budowania aplikacji typu SPA i bez skomplikowanej konfiguracji. W ujęciu słownikowym jest to narzędzie front-end, które rozszerza semantykę HTML o zwięzłe atrybuty, pozwalając zapisywać logikę bezpośrednio w znacznikach. Dzięki temu deweloperzy mogą realizować powszechne zadania interfejsu – od rozwijanych paneli i walidacji formularzy, przez dynamiczne listy i proste stany aplikacji, po animacje przejść – w sposób czytelny, deklaratywny i zgodny z zasadami progressive enhancement. Alpine.js bywa nazywany „jQuery dla czasów nowoczesnego front‑endu”, ale bliżej mu do miniaturowej wersji Vue, bo oferuje mały, reaktywny rdzeń działający bezpośrednio w przeglądarce.

Czym jest Alpine.js i skąd się wziął

Alpine.js powstał jako odpowiedź na potrzebę rozsądnego środka między „gołym” JavaScriptem a rozbudowanymi frameworkami SPA. Twórcą jest Caleb Porzio, który inspirował się składnią i pomysłami z Vue (m.in. atrybutami w stylu x-…), ale za główny cel obrał minimalizm i niską barierę wejścia. Biblioteka jest udostępniana na licencji MIT i rozprowadzana jako pojedynczy plik do włączenia przez CDN lub lokalnie, co eliminuje wymóg narzędzi buildujących. Dla wielu zespołów oznacza to szybszy start, krótszy czas wdrożenia i mniejszą złożoność w utrzymaniu.

W warstwie ideowej Alpine.js wpisuje się w koncepcję „HTML‑first”: to znacznik HTML jest miejscem, w którym opisuje się zachowanie komponentów interfejsu. Zamiast tworzyć skomplikowaną strukturę plików i łańcuchów kompilacji, dodaje się atrybuty, które bezpośrednio wiążą dane, zdarzenia i widoczność elementów. Taki model bywa szczególnie atrakcyjny w serwisach generowanych po stronie serwera (SSR) – PHP (np. Laravel Blade), Ruby on Rails, Django, czy w systemach CMS jak WordPress – gdzie Alpine.js może subtelnie ożywić gotowy markup.

W definicji słownikowej Alpine.js to: mały mikroframework do interaktywnych interfejsów, oparty na paradygmacie HTML‑first i mechanizmie reaktywności, który udostępnia zbiór atrybutów (tzw. dyrektyw) ułatwiających wiązanie danych i obsługę zdarzeń bezpośrednio w znacznikach.

Filozofia i kluczowe cechy

Filozofia Alpine.js sprowadza się do trzech założeń. Po pierwsze, minimalizm: biblioteka ma mały rozmiar, prosty interfejs i niski koszt poznania. Po drugie, praca blisko HTML: logika interfejsu jest deklarowana w atrybutach, co czyni kod łatwym do śledzenia i modyfikacji przez osoby znające standardowy HTML. Po trzecie, brak przymusu kompilacji i narzędzi: Alpine działa natychmiast w przeglądarce, co ułatwia prototypowanie i wdrażanie drobnych zmian.

Na poziomie praktycznym oznacza to, że tworzysz element z atrybutem x-data, definiujesz stan komponentu w prostym obiekcie, a następnie używasz x-bind (skrót „:”) do łączenia właściwości z atrybutami elementów (np. disabled, class), x-on (skrót „@”) do wiązania obsługi zdarzeń, x-show lub x-if do warunkowego renderowania, x-model do dwukierunkowego powiązania pól formularza z danymi oraz x-transition do animacji pokazywania i ukrywania elementów. Każda z tych konstrukcji mapuje fragment logiki aplikacji na czytelny zapis w znaczniku.

Sposób myślenia promowany przez Alpine.js bywa określany jako styl deklaratywny. Zamiast pisać instrukcje krok po kroku „co zrobić”, opisujesz „jaki stan ma mieć interfejs” przy danych warunkach. Gdy dane się zmieniają, biblioteka automatycznie aktualizuje widok. Takie podejście ogranicza liczbę błędów i ułatwia mentalny model – widzisz zależności tam, gdzie powstają: w HTML.

Kolejna cecha to brak ciężkiego routera czy warstwy globalnego zarządzania stanem – Alpine.js celuje w mniejsze interfejsy, widoki i mikrointerakcje. Nie jest to konkurent pełnych SPA, ale idealny dodatek wszędzie tam, gdzie potrzebna jest zwinna interaktywność, bez tworzenia całej aplikacji jednopodstronowej.

Warto też podkreślić, że Alpine.js świetnie realizuje ideę „progressive enhancement”: strona działa i jest zrozumiała bez JavaScriptu (np. dzięki serwerowemu renderowaniu treści), a biblioteka dodaje warstwę interaktywną, gdy skrypt się załaduje. Dla wielu projektów przekłada się to na lepszą dostępność, mniejsze ryzyko awarii i stabilne SEO.

W tym duchu często mówi się o Alpine.js jako o bardzo małym, lecz pełnowartościowym frameworku do tworzenia komponentów w stronach SSR: masz reaktywność, deklaratywną składnię, wiązania atrybutów i klas, pętle, warunki oraz przejścia – i to wszystko bez konfiguracji narzędzi.

Słowniczek pojęć i dyrektywy Alpine.js

Poniżej zestawienie najważniejszych pojęć i atrybutów używanych w Alpine.js, opisane w formie mini‑słownika. Dzięki nim można szybko rozpoznać możliwości biblioteki i powiązać je z typowymi zadaniami w interfejsach WWW.

  • x-data – deklaruje lokalny obiekt danych komponentu. To punkt startowy, w którym definiujesz pola i metody używane w widoku. Każdy element z x-data tworzy własny zasięg (scope).
  • x-init – uruchamia wyrażenie przy inicjalizacji komponentu. Użyteczne do pobrania danych, ustawienia wartości początkowych lub podpięcia nasłuchów szczególnych zdarzeń.
  • x-bind (skrót „:”) – wiąże atrybut HTML z wyrażeniem. Przykłady: :class do dynamicznych klas, :disabled do warunkowego wyłączania, :aria-expanded dla atrybutów ARIA.
  • x-on (skrót „@”) – łączy zdarzenie DOM z wyrażeniem lub funkcją. Przykłady: @click, @input, @keyup.enter. Obsługuje modyfikatory, np. @click.prevent.
  • x-model – dwukierunkowe wiązanie wartości pola formularza z danymi. Działa z input, select, textarea i wspiera modyfikatory, np. x-model.lazy.
  • x-show – warunkowo pokazuje/ukrywa element przez manipulację stylem display; dobrze współgra z x-transition dla płynnych animacji.
  • x-if – warunkowo renderuje element w drzewie. W odróżnieniu od x-show element jest fizycznie dodawany lub usuwany z DOM.
  • x-for – iteruje po kolekcjach i renderuje wielokrotne elementy. Wspiera indeksy, rozpakowywanie wartości i klucze poprawiające wydajność aktualizacji.
  • x-transition – deklaruje animacje wejścia i wyjścia dla elementów pojawiających się lub znikających. Oferuje gotowe klasy i proste sterowanie czasem trwania.
  • x-ref – nadaje „referencję” elementowi, by odwołać się do niego w wyrażeniach (np. do ustawienia focus, odczytania wymiarów).
  • x-cloak – ukrywa elementy do czasu pełnego zainicjalizowania komponentu, zapobiegając migotaniu nieprzetworzonych danych.
  • x-effect – deklaruje efekt, który uruchamia się, gdy zmienią się użyte w nim dane. Przydatne do reakcji na stan bez ręcznej subskrypcji.
  • $store – mechanizm prostych, globalnych magazynów (stores), pozwalających dzielić dane między komponentami bez pełnoskalowego zarządzania stanem.
  • $el, $refs, $watch, $nextTick – wbudowane narzędzia ułatwiające interakcje z elementem, obserwowanie zmian i kolejkowanie aktualizacji.

Te pojęcia pokrywają najczęstsze potrzeby typowego interfejsu: od pętli i warunków, przez dynamiczne klasy i atrybuty, po animacje i efekty zależne od stanu. Co ważne, wszystkie są powiązane z HTML i widoczne bezpośrednio w znacznikach, co ułatwia przeglądanie i utrzymanie kodu.

W szerszym kontekście warto rozumieć terminy stojące za biblioteką: reaktywność, wiązanie danych, cykl życia komponentu, zależności i izolacja stanów. Każdy z tych konceptów w Alpine.js został uproszczony tak, by był dostępny bez dodatkowej konfiguracji i bez ciężkiego środowiska narzędziowego.

Jak działa reaktywność i cykl życia

Serce Alpine.js to mechanizm reaktywności. Biblioteka „otacza” obiekt danych specjalną warstwą, która potrafi rozpoznawać odczyty i zapisy właściwości. Kiedy dane się zmieniają, Alpine potrafi obliczyć, które fragmenty interfejsu są zależne od zmienionej wartości, i zaktualizować je w najbardziej bezpośredni sposób. Zamiast pełnego renderu jak w wirtualnym DOM, aktualizacja dotyka tylko tych atrybutów, tekstów i elementów, które wymagają zmiany, co bywa efektywne dla małych komponentów i umiarkowanych interakcji.

W praktyce cykl życia komponentu obejmuje: inicjalizację (x-data, x-init), przypięcie reaktywnych obserwatorów, przeprowadzenie pierwszego „przejścia” renderu, a następnie nasłuchiwanie na zdarzenia i mutacje. Kiedy następuje zmiana, aktualizacja może zostać opóźniona do najbliższej klatki (nextTick), by skupić wiele modyfikacji i uniknąć nadmiernej liczby przeliczeń. Dodatkowo x-effect umożliwia definiowanie reakcji zależnych od danych poza stricte widokowymi powiązaniami, np. do integracji z API przeglądarek.

Wiązanie danych jest proste: używasz x-model do dwukierunkowych zależności między polami formularza a obiektem danych, lub x-bind do powiązań jednokierunkowych z atrybutami i właściwościami elementów. Alpine wspiera także kontrolę klas (np. warunkowe dodawanie/odejmowanie), a w pętlach x-for opiera się na kluczach, by skracać drogę aktualizacji. Dzięki temu biblioteka zachowuje równowagę między deklaratywnością a przewidywalnością zachowań.

Ważne jest również rozumienie różnicy między x-show i x-if. Pierwsze tylko steruje stylem wyświetlania, przez co element pozostaje w drzewie DOM (np. zachowuje fokus lub stan formularza). Drugie fizycznie dodaje/usuwa węzły, co może być korzystne dla wydajności przy dużych strukturach, ale ma konsekwencje dla dostępności i zachowania fokusów – dlatego przy przełączaniu zaawansowanych widoków warto skorzystać z x-transition i przemyśleć zachowanie klawiatury.

W reaktywnym rdzeniu szczególną rolę mają też narzędzia do obserwacji: $watch pozwala „podsłuchiwać” konkretną właściwość i reagować na jej zmiany efektami ubocznymi, a $nextTick kolejkuje działania do wykonania po zakończeniu bieżącej serii aktualizacji. Współpraca tych mechanizmów umożliwia budowanie płynnych, przewidywalnych interfejsów bez ręcznego zarządzania wieloma zdarzeniami.

Wzorce użycia i integracje w ekosystemie WWW

Alpine.js najczęściej pełni rolę lekkiej warstwy interaktywnej w aplikacjach renderowanych na serwerze. Popularne środowiska to Laravel Blade i Livewire (gdzie Alpine stanowi naturalny partner do interakcji po stronie przeglądarki), Rails (turbo/Hotwire), Django, Phoenix LiveView, a także tradycyjne CMS-y (WordPress, Craft, Statamic). Wszędzie tam, gdzie serwer dostarcza gotowy HTML, Alpine potrafi nadać mu „drugi oddech” bez przebudowy architektury.

Przykładowe wzorce użycia obejmują: akordeony i rozwijane panele, przyklejane nagłówki, walidację formularzy i dynamiczne wskazówki, filtry list i tabel, sortowanie po stronie przeglądarki, lekkie koszyki w e‑commerce, podpowiedzi wyszukiwania, galerie i lightboxy, a także sterowanie modalami i powiadomieniami. Tego typu elementy nie wymagają pełnej aplikacji jednopodstronowej – potrzebują tylko sprytnej warstwy na styku HTML i JavaScript.

W integracjach ze stylami często pojawia się Tailwind CSS. Alpine i Tailwind tworzą parę, w której klasy użytkowe nadają wygląd, a Alpine steruje ich warunkowym włączaniem. Dzięki prostemu :class możesz łatwo przełączać stany aktywny/nieaktywny, wyświetlony/ukryty, wybrany/niewybrany. Alpine dobrze współpracuje też z bibliotekami a11y, narzędziami do focus managementu i prostymi pluginami animacyjnymi.

Jeśli chodzi o dane zewnętrzne, najprostszą drogą jest użycie fetch i aktualizacja lokalnego obiektu x-data. Gdy scenariusz obejmuje synchronizację z serwerem w czasie rzeczywistym, można łączyć Alpine z narzędziami WebSocket/SSE albo z rozwiązaniami typu Livewire/Hotwire, którym Alpine dostarcza elastyczną warstwę interakcji w przeglądarce. Sprawdza się to w miejscach, gdzie część interfejsu aktualizuje się „sama”, a użytkownik ma zapewnioną płynną interakcję bez pełnego przeładowania.

Alpine ma również prosty ekosystem dodatków: wtyczki rozszerzają składnię o kolejne możliwości (np. maski w polach formularzy, skróty klawiaturowe, interakcje zewnętrzne). Dzięki temu rdzeń pozostaje mały, a specyficzne potrzeby można zaspokajać przez dołączanie niewielkich rozszerzeń tylko wtedy, gdy są potrzebne.

Zależnie od skali projektu warto rozważyć separację komponentów: dzielenie widoku na mniejsze segmenty x-data, wykorzystanie $store do wspólnych danych oraz stosowanie konwencji nazewniczych w x-ref i klasach, co ułatwia testowanie i utrzymanie. Choć Alpine nie narzuca złożonej struktury katalogów, odrobina dyscypliny projektowej przekłada się na długoterminową czytelność kodu.

Porównanie z innymi podejściami

W relacji do jQuery Alpine.js eliminuje imperatywne „szukanie i manipulowanie” na rzecz powiązań deklarowanych w HTML. Zamiast manualnie podpinać zdarzenia i dbać o stan elementów, opisujesz zależność w atrybutach. Taki model bywa mniej podatny na rozjechanie logiki i łatwiejszy we współpracy zespołowej, bo znika konieczność czytania wielu handlerów rozsianych po plikach.

Porównując z Vue i React, Alpine jest znacznie mniejszy i prostszy. Nie ma rozbudowanego systemu komponentów z kompilatorem szablonów, routera, systemu SSR czy narzędzi do budowania ogromnych SPA. W zamian dostajesz szybki start, niską złożoność i idealne dopasowanie do projektów SSR oraz mikrointerakcji. Jeżeli aplikacja ma kilkadziesiąt widoków, złożone przepływy, routing po stronie klienta, duże wymagania względem testów jednostkowych i integracyjnych – wtedy pełny framework SPA bywa lepszym wyborem.

W zestawieniu ze Stimulus/Hotwire Alpine stawia na reaktywność danych w samym kliencie i deklaratywne wiązania w HTML. Stimulus preferuje klasowy model kontrolerów przypinanych do elementów i zostawia zarządzanie stanem po stronie JS lub back-endu (np. Turbo). W wielu projektach te podejścia współgrają: Hotwire zapewnia aktualizacje po stronie serwera, a Alpine wzmacnia interaktywną logikę w przeglądarce.

Względem HTMX Alpine pełni inną rolę: HTMX przenosi część odpowiedzialności za akcje do atrybutów HTML, ale w kontekście komunikacji z serwerem (żądania, częściowe przeładowania). Alpine natomiast skupia się na stanie i interakcji w przeglądarce. Razem tworzą ciekawy duet – HTMX dostarcza fragmenty HTML z serwera, a Alpine utrzymuje ich dynamiczne zachowanie lokalnie.

Klucz, by dokonać właściwego wyboru, to zrozumienie skali i charakteru projektu. Jeśli potrzeba dodać kilka interakcji do już istniejącej strony, Alpine zwykle jest najprostszą ścieżką. Jeżeli jednak wymagania rosną w kierunku wielkiego SPA, naturalną drogą pozostają narzędzia klasy Vue/React/Svelte.

Praktyka: dostępność, bezpieczeństwo, testy, wydajność

Dostępność (a11y) w Alpine zaczyna się od poprawnego HTML. Dyrektywy nie zastąpią semantyki; to na projektancie i deweloperze spoczywa obowiązek użycia właściwych ról, labeli i struktury nagłówkowej. Następnie dochodzi kwestia sterowania fokusem: przy modalach, rozwijanych panelach czy listach dynamicznych trzeba zarządzać kolejnością tabulacji, zawężeniem fokusu do aktywnego kontekstu i prawidłowym przywróceniem po zamknięciu. x-ref i narzędzia Alpine ułatwiają skupienie i monitorowanie stanu, a x-show/x-if powinny być dobierane świadomie, by nie „gubić” punktu uwagi użytkownika klawiatury.

Obsługa screen readerów wymaga spójnych atrybutów ARIA oraz informowania o zmianach treści. W zależności od scenariusza można wykorzystać aria-live lub programowe „anonsowanie” kluczowych zdarzeń. W praktyce drobna współpraca z QA lub specjalistą a11y przynosi duże korzyści, bo wiele wzorców (akordeon, menu rozwijane, dialog) ma utrwalone rekomendacje WAI-ARIA, które łatwo pożenić z Alpine.

Bezpieczeństwo koncentruje się na unikaniu wstrzyknięć HTML/JS. Najważniejsza zasada: ostrożnie z x-html – renderuje on surowy HTML, dlatego powinien być używany tylko dla treści zaufanych lub po solidnej sanitacji po stronie serwera. Dodatkowo polityki CSP mogą ograniczać eval i inline scripts; Alpine jest zwykle przyjazny CSP, ale w surowych konfiguracjach warto dostroić nagłówki (np. zezwolić na nonce dla skryptów). W obsłudze danych z zewnętrznych API należy zawsze walidować i filtrować odpowiedzi oraz nie wiązać bezpośrednio nieprzewidzianych wartości z atrybutami, które mogą wpływać na uruchamianie skryptów.

Testowanie w Alpine dobrze realizują testy E2E (Cypress, Playwright), które odwzorowują realne interakcje: kliki, wpisywanie tekstu, nawigacja klawiaturą. Dla testów jednostkowych można wspomóc się środowiskiem JSDOM lub lekkim runnerem przeglądarkowym; celem jest sprawdzenie, czy reakcje na zdarzenia i zmiany stanu aktualizują odpowiednie fragmenty interfejsu. Warto też rozważyć snapshoty HTML dla krytycznych komponentów, by szybko wykrywać niezamierzone różnice w strukturze.

Wydajność w Alpine opiera się na kilku prostych regułach. Należy utrzymywać komponenty małe i wyspecjalizowane, rozbijać duże listy na paginowane sekcje, korzystać z kluczy w x-for oraz rozważnie wybierać między x-show (zachowanie elementu w drzewie) a x-if (dodawanie/usuwanie). Obciążające obliczenia warto odkładać do $nextTick lub memoizować. Dobrą praktyką jest też delegacja zdarzeń – zamiast wielu handlerów na elementach podrzędnych, jeden na elemencie wyżej, który rozpoznaje cel akcji. Wreszcie, monitorowanie rzeczywistego zachowania w narzędziach deweloperskich przeglądarki pozwala szybko wykryć wąskie gardła.

Organizacja kodu sprzyja utrzymaniu: konsekwentne nazewnictwo właściwości, unikanie nadmiernych efektów ubocznych w x-init, przechowywanie logiki w metodach (zamiast długich wyrażeń inline) oraz dokumentowanie znaczenia kluczowych flag. To sprawia, że komponenty są zrozumiałe po czasie, a ich modyfikacja nie pociąga kaskady niespodzianek.

Podstawowe terminy w kontekście Alpine.js

Żeby lepiej uchwycić definicję, dobrze jest skojarzyć Alpine.js z kilkoma kluczowymi słowami, które opisują jego naturę i sposób pracy.

  • reaktywny – zmiana danych automatycznie powoduje aktualizację widoku; nie trzeba ręcznie odświeżać elementów.
  • dyrektywy – atrybuty x-… w HTML, które wyrażają wiązania, zdarzenia, pętle, warunki i efekty.
  • komponenty – wydzielone fragmenty interfejsu ogrodzone lokalnym x-data; ich zakres jest izolowany i łatwo je przenosić.
  • stan – lokalne dane trzymane w x-data lub współdzielone w $store; to one determinują, co wyświetla interfejs.
  • binding – wiązanie danych i atrybutów (np. :class, x-model) oraz reakcja na zmiany bez ręcznego manipulowania elementami.
  • zdarzeniainterakcje użytkownika (klik, klawiatura, wprowadzanie tekstu) i systemu, obsługiwane przez x-on/@….
  • DOM – drzewo dokumentu, na którym Alpine wykonuje precyzyjne, małe aktualizacje wymaganych węzłów.
  • mikroframework – z definicji niewielki zestaw funkcji, który rozwiązuje konkretne zadania bez narzucania rozbudowanej architektury.
  • framework – szerszy ekosystem pozwalający budować komponenty i interakcje w przewidywalnym modelu, tu w wersji skondensowanej.
  • deklaratywny – styl zapisu, w którym opisujesz docelowy stan interfejsu, a biblioteka dba o detale aktualizacji.

Te terminy tworzą praktyczny słowniczek, który pozwala szybko zrozumieć, czym Alpine.js jest na tle innych narzędzi i jak wpasowuje się w proces tworzenia stron WWW. Warto zauważyć, że choć biblioteka bywa określana zdrobniale, jej paradygmaty są dojrzałe i spójne z najlepszymi praktykami współczesnego front‑endu.

FAQ

  • Co to jest Alpine.js w najprostszych słowach?
    Lekka biblioteka JavaScript do dodawania interaktywności bezpośrednio w HTML za pomocą atrybutów, bez konieczności budowania pełnej aplikacji SPA.
  • Do czego najlepiej użyć Alpine.js?
    Do akordeonów, modalów, walidacji formularzy, dynamicznych list, filtrowania, przełączników, lekkich koszyków, animacji przejść i wszelkich mikrointerakcji w stronach renderowanych na serwerze.
  • Czy Alpine.js wymaga narzędzi buildujących?
    Nie. Wystarczy dodać skrypt z CDN lub lokalny plik. Można oczywiście użyć bundlera w większych projektach, ale nie jest to warunek działania.
  • Jak duży jest Alpine.js?
    Zazwyczaj to kilkanaście kilobajtów po kompresji gzip; rozmiar zależy od wersji i użytych dodatków.
  • Czy Alpine.js nadaje się do dużych SPA?
    Nie jest to jego główny cel. Alpine najlepiej sprawdza się w mniejszych interfejsach i stronach SSR. Do dużych SPA lepsze będą Vue/React/Svelte.
  • Jak wypada SEO z Alpine.js?
    Dobrze, szczególnie gdy treść jest renderowana po stronie serwera. Alpine dodaje zachowanie po załadowaniu skryptu, więc indeksacja nie cierpi jak przy czystym SPA.
  • Czy Alpine.js wspiera TypeScript?
    Można korzystać z TS w projekcie, lecz sam Alpine nie wymaga TS. W praktyce typowanie dotyczy twojego kodu i integracji, a Alpine konsumuje wynik transpilacji do JS.
  • Jakie są typowe pułapki bezpieczeństwa?
    Niebezpieczne jest nieostrożne użycie x-html z niezaufanymi danymi. Należy też respektować polityki CSP i walidować/odkażać dane z zewnętrznych źródeł.
  • Czy Alpine.js działa z frameworkami back-endowymi?
    Tak. Jest często używany z Laravel Blade/Livewire, Rails (Hotwire), Django, Phoenix i CMS-ami. Wystarczy wstawić atrybuty w generowany HTML.
  • Kiedy nie używać Alpine.js?
    Gdy potrzebujesz rozbudowanego routingu po stronie klienta, skomplikowanego globalnego stanu, SSR w przeglądarce lub zaawansowanego renderingu – wówczas pełny framework SPA będzie właściwszy.
  • Czy można łączyć Alpine.js z innymi bibliotekami front-end?
    Tak. Typowe połączenia to Tailwind CSS, HTMX, Hotwire, a także drobne wtyczki do masek, skrótów klawiaturowych i animacji.
  • Jak zacząć w istniejącym projekcie?
    Dołącz skrypt Alpine, odnajdź fragment interfejsu wymagający interakcji, dodaj x-data i stopniowo rozszerzaj markup o dyrektywy x-bind, x-on, x-show/x-if i x-model.

Chcesz mieć dobrą stronę internetową?

Zadzwoń do nas. Porozmawiamy o stronie dopasowanej
do Twoich potrzeb.

601 162 666

Poprzedni wpis
Czym są certyfikaty SSL i jak je zainstalować
Następny wpis
Strona internetowa na WordPress dla księgowej
Zadzwoń Konsultacja