Lżej i szybciej — przewodnik po Svelte Framework
Opublikowany: 2022-03-11Aplikacje internetowe z dnia na dzień stają się coraz bardziej popularne. To rozwijający się świat, który ludzie wybierają ze względu na jego prostotę, szybkość i dostępność na wielu platformach. Ogromną rolę w tym procesie wzięły aplikacje jednostronicowe (SPA). Struktury, takie jak Angular, Vue.js i React, pomagają programistom zapewnić najlepsze wrażenia użytkownika w krótkim czasie, pozostawiając kod, który można obsługiwać i rozszerzać. Narzędzia te od dawna cieszą się największą popularnością w branży, z wieloma zaletami w stosunku do nowo tworzonych pakietów. Poczuł się jak oligopol w świecie SPA. Jednak grupa patrzących w przyszłość deweloperów, których celem jest ten rynek, może wejść z poważnym konkurentem – Svelte.
Svelte to nowe podejście do budowania interfejsów użytkownika. Zanurzmy się i zbadajmy, co sprawia, że jest tak świeży, tworząc wspólny formularz logowania.
Architektura
Svelte został zaprojektowany tak, aby był szybszy niż jakakolwiek inna biblioteka. Osiąga się to poprzez przesunięcie kroku ładowania frameworka do budowy wirtualnego DOM. Zamiast używać narzędzia podczas procesu, jest kompilowane do waniliowego JS na etapie budowania, więc aplikacja nie wymaga żadnych zależności do uruchomienia.
Smukły | Inne biblioteki SPA (React, Vue.js, Angular itp.) |
---|---|
1. Otwórz stronę internetową | 1. Otwórz stronę internetową |
Powyższa tabela opisuje, dlaczego Svelte jest absolutnym zwycięzcą pod względem wydajności startupów. Nie jest to osiągane przez jakąkolwiek optymalizację, ale przez użycie dostępnego kompilatora JavaScript przeglądarki zamiast kompilatora bocznego.
Instalacja
Montaż Svelte jest niezwykle łatwy, dzięki czemu jego użytkowanie jest bardzo przyjemne. Pierwszym krokiem jest pobranie szablonu projektu:
npx degit sveltejs/template svelte-login-form
Wykonanie powyższego polecenia oznacza, że mamy szablon projektu Svelte. Na razie jest pusty, a wymagane pakiety NPM nie są jeszcze zainstalowane. Naprawmy to.
cd svelte-login-form npm install
Teraz aplikacja jest gotowa do uruchomienia za pomocą następującego polecenia:
npm run dev
Struktura
Każdy komponent Svelte może zawierać następujące sekcje:
- Scenariusz
- Styl
- Szablon
Spójrzmy na przykład w pliku src/App.svelte
.
<script> export let name; </script> <style> h1 { color: purple; } </style> <h1>{name}</h1>
Powyższy kod zawiera dokładnie trzy sekcje:
znacznik
script
, który jest opcjonalnym blokiem JavaScript zawierającym deklaracje zmiennych i funkcji, które powinny być używane wewnątrz komponentu.tag
style
, który jest kolejnym opcjonalnym blokiem. Jest podobny do zwykłego tagu w stylu HTML, z wyjątkiem jednej ważnej różnicy. Reguły opisane w tym bloku dotyczą tylko tego składnika. Zastosowanie stylu do elementup
nie wpłynie na wszystkie akapity na stronie. To fantastyczne, ponieważ nie musisz wymyślać nazw klas i nigdy przypadkowo nie ominiesz innej zasady.Ostatnim i jedynym wymaganym blokiem jest blok szablonu - w tym przypadku znacznik
h1
. Jest to prezentacja/widok twojego komponentu. Jest ściśle powiązany z blokami stylu i skryptu, ponieważ określają one, w jaki sposób widok będzie stylizowany i jak będzie się zachowywał.
Svelte to biblioteka próbująca wprowadzić modułowość do gry front-endowej. Zachowuje tę modułowość nie tylko w oddzielaniu różnych komponentów, ale także w izolowaniu logiki, widoku i szablonu.
Wracając do budowanego przez nas formularza logowania, utwórzmy nowy plik LoginForm.svelte
w folderze src
o następującej treści:
<style> form { background: #fff; padding: 50px; width: 250px; height: 400px; display: flex; flex-direction: column; justify-content: center; align-items: center; box-shadow: 0px 20px 14px 8px rgba(0, 0, 0, 0.58); } label { margin: 10px 0; align-self: flex-start; font-weight: 500; } input { border: none; border-bottom: 1px solid #ccc; margin-bottom: 20px; transition: all 300ms ease-in-out; width: 100%; } input:focus { outline: 0; border-bottom: 1px solid #666; } button { margin-top: 20px; background: black; color: white; padding: 10px 0; width: 200px; border-radius: 25px; text-transform: uppercase; font-weight: bold; cursor: pointer; transition: all 300ms ease-in-out; } button:hover { transform: translateY(-2.5px); box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.58); } h1 { margin: 10px 20px 30px 20px; font-size: 40px; } </style> <form> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" /> <label>Password</label> <input name="password" type="password" placeholder="password" /> <button type="submit">Log in </button> </form>
Jest to element o głupim stylu, który później ulepszymy. Aby zobaczyć ten komponent na naszej stronie, należy go wyrenderować w głównym komponencie - App. Przejdźmy do edycji src/App.svelte
, aby wyglądał tak:
<script> import LoginForm from "./LoginForm.svelte"; </script> <style> section { height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; background: linear-gradient(to right, #cd76e2, #e358ab); } </style> <section> <LoginForm /> </section>
Jeśli wszystko zostało zrobione poprawnie, a aplikacja nadal działa, nasz formularz pojawi się na localhost:5000
. Podnieśmy poziom naszych umiejętności Svelte, ulepszając formularz.
Staje się stanowczy
Każdy komponent w Svelte może mieć swój stan. Stan jest zmienną specjalną lub grupą zmiennych specjalnych, których można użyć wewnątrz szablonu. Dlaczego mówię „specjalny”? Za każdym razem, gdy taka zmienna zostanie zmieniona, szablon jest o tym powiadamiany i renderuje treść w najnowszym stanie. Dzięki temu aplikacja bardzo szybko reaguje na interakcje użytkownika.
Zadeklarujemy zmienne stanu adresu e- email
i password
, w których będą przechowywane wartości formularzy dla odpowiednich pól. Oznacza to, że nasze zmienne adresu e- email
i password
będą zawsze zsynchronizowane z wartościami formularza, dzięki czemu będziemy gotowi do przesłania tych wartości w dowolnym momencie bez obaw o jakiekolwiek różnice między wartościami przesłanymi a rzeczywistymi wartościami w formularzu.
<script> let email = ""; let password = ""; let isLoading = false; const handleSubmit = () => { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); }; </script> <style> /* Style is unchanged */ </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> {#if isLoading}Logging in...{:else}Log in {/if} </form>
Zmienne stanu wyglądają jak zwykłe zmienne JavaScript, ale aby były zsynchronizowane z wartościami formularza (powiązać je z polami formularza), konieczne jest użycie dyrektywy bind:value
. Jest też kilka nieznanych rzeczy:
on:submit|preventDefault
jest skrótem do zapobiegania domyślnemu zachowaniu zdarzeń. Jest to wygodniejsze niż pisanie za każdym razeme.preventDefault()
.{#if isLoading}Logging in...{:else}Log in {/if}
to fragment składni szablonu Svelte. Ponieważ w bloku szablonu nie ma JS, istnieje specjalna składnia do używania ifs, pętli itp.
Na koniec skorzystajmy z dostępnych opcji, używając stanu, aby dodać walidację do naszego formularza. Można to osiągnąć poprzez utworzenie kolejnej zmiennej stanu errors
, która zostanie wypełniona błędami, gdy formularz zostanie przesłany z nieprawidłowymi wartościami.
<script> let email = ""; let password = ""; let isLoading = false; let errors = {}; const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; // Authorize the user }, 1000); } }; </script> <style> // Previous styles unchanged .errors { list-style-type: none; padding: 10px; margin: 0; border: 2px solid #be6283; color: #be6283; background: rgba(190, 98, 131, 0.3); } </style> <form on:submit|preventDefault={handleSubmit}> <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} </form>

Formularz jest prawie gotowy. Jedyne, co pozostaje, to komunikat o sukcesie po pomyślnym uwierzytelnieniu.

Utwórzmy zmienną stanu do śledzenia udanych zgłoszeń, która domyślnie ma wartość false
. Po pomyślnym przesłaniu formularza wartość tej zmiennej powinna zostać ustawiona na true
.
let isSuccess = false;
Należy również zmienić funkcję obsługującą przesyłanie formularza, aby była zgodna z logiką przełączania isSuccess
po udanej operacji.
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; // Simulate network request setTimeout(() => { isLoading = false; isSuccess = true; // Authorize the user }, 1000); } };
Ta modyfikacja sprawia, że formularz przechodzi w stan powodzenia zaraz po zakończeniu przesyłania.
Ale jeśli sprawdzisz serwer deweloperski, nie znajdziesz żadnych zmian w zachowaniu formularza. Zmieniliśmy kod, ale nie dotknęliśmy jeszcze szablonu. Musimy dodać instrukcje do szablonu, aby wyświetlić komunikat o sukcesie, gdy użytkownik pomyślnie się zalogował. Składnia szablonu Svelte pozwala nam to łatwo zaimplementować:
<form on:submit|preventDefault={handleSubmit}> {#if isSuccess} <div class="success"> <br /> You've been successfully logged in. </div> {:else} <h1></h1> <label>Email</label> <input name="email" placeholder="[email protected]" bind:value={email} /> <label>Password</label> <input name="password" type="password" bind:value={password} /> <button type="submit"> {#if isLoading}Logging in...{:else}Log in {/if} </button> {#if Object.keys(errors).length > 0} <ul class="errors"> {#each Object.keys(errors) as field} <li>{field}: {errors[field]}</li> {/each} </ul> {/if} {/if} </form>
Abstrakt z właściwościami
Uporządkowaliśmy wszystko na temat stanu komponentów wewnętrznych. Teraz nadszedł czas, aby przejść przez zewnętrzne zależności zwane właściwościami lub „rekwizytami”. Rekwizyty to dane wejściowe lub argumenty przekazywane do komponentu, aby opisać komponentowi, co powinno się pojawić lub jak komponent powinien się zachowywać.
Deklaracja właściwości wygląda podobnie do stanu, z wyjątkiem słowa kluczowego export
.
<script> export let answer; </script> <p>The answer is {answer}</p>
<script> import Nested from './Nested.svelte'; </script> <Nested answer={42}/>
Chodzi o właściwości. Zadeklaruj i przekaż - wszystko, co musisz wiedzieć, aby używać rekwizytów.
Ale jak te właściwości odnoszą się do komponentu formularza logowania? Rekwizyty mogą sprawić, że nasz formularz logowania będzie bardziej ogólny, wyodrębniając funkcję przesyłania do właściwości. Pozwoli ci to na użycie tego komponentu z dowolną akcją przesyłania, której potrzebujesz (żądanie do serwera testowego, żądanie do rzeczywistego serwera itp.). Ta podpowiedź będzie nazywana submit
i będzie funkcją, która zwróci rozwiązaną obietnicę, jeśli akcja submit się powiodła, i odrzuconą obietnicę, jeśli wystąpi błąd. Zadeklarujmy podporę za pomocą powyższego przykładu:
export let submit;
Należy również edytować procedurę obsługi zgłoszeń w formularzu logowania, aby korzystać z nowej właściwości submit
.
const handleSubmit = () => { errors = {}; if (email.length === 0) { errors.email = "Field should not be empty"; } if (password.length === 0) { errors.password = "Field should not be empty"; } if (Object.keys(errors).length === 0) { isLoading = true; submit({ email, password }) .then(() => { isSuccess = true; isLoading = false; }) .catch(err => { errors.server = err; isLoading = false; }); } };
Komponent wydaje się być gotowy. Jeśli jednak wrócisz do formularza i spróbujesz go przesłać, zauważysz, że stan przycisku nie zmienił się od momentu załadowania. Ponadto istnieje wyjątek w konsoli: Uncaught TypeError: submit is not a function
. Oczywiście zadeklarowaliśmy rekwizyt, ale zapomnieliśmy go przekazać. Zadeklarujmy funkcję w komponencie app i przekażmy ją do formularza logowania.
const submit = ({ email, password }) => new Promise((resolve, reject) => setTimeout(resolve, 1000));
<section> <LoginForm submit={submit} /> </section>
Teraz formularz działa zgodnie z przeznaczeniem. Może zarówno pokazywać błędy, jak i informować użytkownika, czy logowanie powiodło się.

Udostępnianie kontekstu
Wygląda na to, że wymieniono wszystko, co jest potrzebne do zbudowania aplikacji. Z właściwościami i stanem wewnętrznym jesteśmy gotowi do pracy. Ale to tylko częściowo prawda. Te dwa ogólne punkty umożliwiają projektowanie OSO o dużej złożoności. Jeśli jednak spróbujesz udostępniać dane między wieloma różnymi komponentami, będzie to bardzo trudne.
Najprostszym przykładem jest posiadanie globalnie dostępnej zmiennej user
. Wiele komponentów powinno zmienić swoje zachowanie związane z użytkownikiem, w zależności od jego roli, wieku, statusu itp. Nie jest jednak DRY powtarzanie się poprzez przekazywanie użytkownika do każdego komponentu w aplikacji za pomocą rekwizytów.
Svelte ma na to rozwiązanie: kontekstowe API.
Interfejs API kontekstu zapewnia mechanizm „komunikacji” komponentów ze sobą bez przekazywania danych i działa jako właściwości lub wysyłanie wielu zdarzeń. To zaawansowana funkcja, ale przydatna.
Dodajmy kontekst użytkownika do projektowanego przez nas formularza logowania. Utwórz plik userContext.js
w folderze src
z następującą zawartością:
export const key = "userContext"; export const initialValue = null;
key
jest unikalnym identyfikatorem kontekstu, ponieważ aplikacja może mieć nieograniczoną liczbę różnych kontekstów, które muszą pozostać dostępne. initialValue
jest tylko wartością domyślną kontekstu przed jej ustawieniem.
Kolejnym krokiem jest dodanie kontekstu do naszej aplikacji. Przejdź do pliku App.svelte
i dodaj 2 instrukcje importu:
import { onMount, setContext } from "svelte"; import { key as userContextKey, initialValue as userContextInitialValue } from "./userContext";
Patrząc na powyższy kod możesz się zastanawiać, co importujemy ze svelte
pakietu. onMount
to funkcja pomocnicza wymagająca funkcji zwrotnej jako argumentu. To wywołanie zwrotne zostanie wykonane podczas montowania bieżącego komponentu (na samym początku ładowania komponentu). setContext
to funkcja ustawiająca kontekst. Wymaga klucza do kontekstu i nowej wartości jako argumentów.
Użyjmy funkcji onMount
, aby ustawić domyślną wartość kontekstu:
onMount(() => { setContext(userContextKey, userContextInitialValue); });
I zmodyfikuj funkcję submit
, aby ustawić kontekst użytkownika:
const submit = ({ email, password }) => new Promise((resolve, reject) => { setTimeout(() => { setContext(userContextKey, { name: "Foo", lastName: "Bar", email: "[email protected]" }); resolve(); }, 1000); });
Otóż to. Pomyślne przesłanie zmieni kontekst użytkownika na fałszywy obiekt użytkownika, do którego można uzyskać dostęp poprzez getContext
pobierający kontekst :
<script> import { getContext } from 'svelte'; import { key as userContextKey } from "./userContext"; const user = getContext(key); </script>
Streszczenie
Svelte to potężne narzędzie o wysokiej wydajności i elastycznym interfejsie API. Oprócz podstaw opisanych w tym poście, Svelte ma następujące funkcje po wyjęciu z pudełka:
- Deklaracje i oświadczenia reaktywne
- Czekaj na bloki szablonów
- Wiązanie wymiarów
- Globalny sklep jak Redux
- Pomocnicy animacji i przejścia
- Pomocnik debugowania
Podsumowując, Svelte to świetna biblioteka, która spełnia wszystkie potrzeby budowania SPA i nie tylko. Może konkurować z największymi graczami na rynku, a nawet wygrywać. To, czego może teraz użyć, to wsparcie w społeczności programistów front-end.
Uwaga: cały kod w tym artykule można znaleźć w repozytorium GitHub teimurjan/svelte-login-form
. Demo formularza logowania jest dostępne tutaj.