Svelte

Svelte on ohjelmistokehys web-sovellusten kehittämiseen JavaScriptin, HTML:n ja CSS:n avulla. Sille on ominaista muun muassa nopeus ja vakiokoodin () ja erikoissyntaksin vähyys. Nopeus on seurausta erityisesti siitä, että Svelte kääntää sovelluskoodin natiiviksi JavaScriptiksi ja pyrkii näin tekemään vähemmän työtä ajon aikana. Muita vastaavia kehyksiä ovat muun muassa React ja Vue.

Esimerkit

SvelteKit-demo 

SvelteKit-kehyksen sisältämän demosovelluksen tiedostorakenne näyttää seuraavalta:
$ tree --filelimit 20
├── node_modules  [116 entries exceeds filelimit, not opening dir]
├── package.json
├── package-lock.json
├── README.md
├── src
│   ├── app.html
│   ├── lib
│   │   └── images
│   │       ├── github.svg
│   │       ├── svelte-logo.svg
│   │       ├── svelte-welcome.png
│   │       └── svelte-welcome.webp
│   └── routes
│       ├── about
│       │   ├── +page.js
│       │   └── +page.svelte
│       ├── Counter.svelte
│       ├── Header.svelte
│       ├── +layout.svelte
│       ├── +page.js
│       ├── +page.svelte
│       ├── styles.css
│       └── sverdle
│           ├── how-to-play
│           │   ├── +page.js
│           │   └── +page.svelte
│           ├── +page.server.js
│           ├── +page.svelte
│           └── words.server.js
├── static
│   ├── favicon.png
│   └── robots.txt
├── svelte.config.js
└── vite.config.js

Tämä demosovellus sisältää laskurikomponentin tiedostossa Counter.svelte, joka näyttää oleellisilta osin seuraavalta:
<script>
    // Tuo store-objekti, jonka avulla voidaan muuttaa
    // arvo toiseen jatkuvalla tavalla.
	import { spring } from 'svelte/motion';
    // Komponentissa on yksi tilamuuttuja, joka
    // saa kokonaislukuarvoja.
	let count = 0;

    // Käyttäjälle näytetään reaalilukuja.
	const displayed_count = spring();
    // $-nimellä merkityt lauseet ovat reaktiivisia sisältämiensä
    // muuttujien arvojen muutoksille.
	$: displayed_count.set(count);
    // Jos muuttujan nimi alkaa $:lla, se tulkitaan automaattisesti
    // store-objektiksi tavallisen muuttujan sijaan.
	$: offset = modulo($displayed_count, 1);

    // Alla olevaa funktiota käytetään yllä; tämä on sallittua JavaScriptissä 
    // deklaraationa määritellyille funktioille ({{k-en|function hoisting}}).
	function modulo(n, m) {
		return ((n % m) + m) % m;
	}
</script>

<div class="counter">
    <!-- Lisää laskuria vähentävään button-elementtiin nimetön 
         tapahtumankäsittelijä natiiville DOM-tapahtumalle "click". 
         JavaScript tulee kaarisulkeisiin ja päivittää count-muuttujaa.
    -->
	<button on:click={() => (count -= 1)} aria-label="Decrease by one">
        <!-- SVG poistettu -->
	</button>

	<div class="cv">
        <!-- CSS-tyylistä tulee dynaaminen interpoloimalla
             siihen suoraan JavaScriptiä. -->
		<div class="cd" style="transform: translate(0, {100 * offset}%)">
			<strong class="hidden" aria-hidden="true">
                {Math.floor($displayed_count + 1)}
            </strong>
			<strong>
                {Math.floor($displayed_count)}
            </strong>
		</div>
	</div>

	<button on:click={() => (count += 1)} aria-label="Increase by one">
        <!-- SVG poistettu -->
	</button>
</div>

<style>
    /* CSS poistettu */
</style>

Käyttö 

Svelten käyttö onnistuu esim. SvelteKit-työkalun avulla npm create svelte@latest nimi. Tämä edellyttää Node.js-ajoympäristöä ja npm-pakettienhallintaohjelmaa. npm install asentaa sovelluksen riippuvuudet ja npm run dev käynnistää paikallisen kehityspalvelimen. npm run build tuottaa lopullisen sovelluksen konfiguraatiotiedostojen mukaan ja tämä voidaan jakaa halutulla alustalla Node-palvelimella. Osana tätä rakennusprosessia Svelte kääntää tiedostonsa optimoiduksi, natiiviksi JavaScriptiksi (luokaksi).

Rakenne

Komponentit 

Svelte-sovellukset koostuvat komponenteista, jotka ovat itsenäisiä joukkoja JavaScript-, HTML-, CSS-kieltä ja Svelte-syntaksia. Komponentit määritellään omiin tiedostoihinsa. JavaScript tulee script-merkkien väliin ja CSS style-merkkien väliin – loput komponentista on Svelten laajennettua HTML-tyyppistä merkintäkieltä. JavaScriptiä voidaan sekoittaa suoraan merkintäkieleen kaarisulkeissa, kuten <h1>Hello, {name}"</h1> tai . Samalla tavalla esim. style-direktiivi helpottaa CSS-tyylien lisäämistä suoraan elementteihin tyylillä <p style:color={color} style:--cssmuuttuja={jsmuuttuja}>...</p>.

Toisessa tiedostossa esim. Komponentti.svelte määritelty komponentti saadaan käyttöön import-lauseella, minkä jälkeen sitä voidaan käyttää HTML-elementin tavoin . Kun muuttujan (tai lauseen) tulee olla reaktiivinen toisen muuttujan arvon muutokseen, merkitään haluttu lause nimellä $, kuten $: x = teeJotain(y);. Vain muuttujaan sijoittaminen tekee muuttujasta reaktiivisen, eli JavaScript-objektin mutaatio muulla tavalla ei päivitä sovelluksen tilaa. 

Komponentteja määritellessä käytetään slot-elementtiä tyylillä <A><slot></slot></A> kertomaan Sveltelle, mihin komponentin alikomponentit/elementit, kuten <A><B/></A> injektoidaan. Jos mitään injektoitavaa ei anneta <A/>, Svelte käyttää komponenttiin määriteltyä oletuselementtiä .... Jos komponentissa on taas useita slotteja, niille annetaan nimet <slot name="nimi"> ja injektoitava elementti ohjataan sinne attribuutilla <B slot="nimi"/>.

Logiikan lisääminen suoraan komponentin rakenteeseen onnistuu
 ehtolauseilla {#if ...} ... {:else if ...} ... {:else} ... {/if} tai {#key arvo} ... {/key}
 toistolauseella {#each xs as x (x.id)} ... {/each} ja
 asynkroniselle tulokselle (Promise) syntaksilla {#await x} ... {:then y} ... {:catch e} ... {/await} tai lyhyemmin {#await x then y} ... {/await}.

Erityisiin sisäänrakennettuihin Svelte-elementteihin kuuluvat <svelte:self>, <svelte:component this=...>, <svelte:element this=...>, <svelte:window>, <svelte:body>, <svelte:head>, <svelte:options> (kääntäjän asetukset) ja <svelte:fragment>.

Komponenttien tiedonkulku 

Kun alikomponentti tuodaan uuteen komponenttiin, tämän näkymään siirtyvät samalla komponentista jaetut muuttujat eli ns. propsit (), kuten export let muuttuja = "oletusarvo";. Myös slotit hyväksyvät propseja, mutta nämä tulee tuoda näkyviin injektoinnin yhteydessä let-direktiivillä, kuten <Komponentti let:muuttuja={muuttuja}>...</Komponentti>. Tällöin arvo siirtyy siis toiseen suuntaan ylhäältä alas.

Komponenttien kesken voidaan jakaa tietoa myös ilman props-mekanismia kontekstien avulla. Kun komponentti kutsuu setContext-funktiota, kyseinen konteksti (mikä tahansa objekti) on saatavissa alikomponenteissa getContext-kutsulla. Kolmas tapa jakaa tietoa saman komponentin instanssien kesken on käyttää ns. moduulikontekstia: kaikki <script context="module">-merkkien sisällä oleva JavaScript ajetaan vain kerran moduulin ajon aikana, eikä jokaiselle instanssille erikseen.

Käyttäjän antamien arvojen siirtämiseksi ylös komponenttihierarkkiaa tarvitaan bind-direktiiviä, kuten <input bind:attribuutti={muuttuja}>. Eri elementeillä on erilaisia attribuutteja, joiden kanssa voidaan käyttää bind-direktiiviä joko yksi- (lue) tai kaksisuuntaisesti (lue ja kirjoita). bind:this viittaa attribuutin sijasta itse elementtiin, ja useasta elementistä voidaan ohjata arvoja yhteen muuttujaan käyttämällä bind:group-attribuuttia.

Komponenttien ulkopuolisten tilamuuttujien käyttämiseen tarvitaan ns. tietovarastoa (), joka luodaan funktioiden, kuten writable, readable ja derived avulla tyylillä export const x = writable(0);. Tätä muuttujaa käytetään sitten tuonnin jälkeen sen metodien, kuten subscribe, set ja update kautta. Metodien suora käyttö voidaan myös välttää dollarisyntaksilla $muuttuja – Svelte tulkitsee tällaisen nimen aina varastoksi.

Tapahtumienhallinta 

Tapahtumankäsittelijän liittämiseksi komponentin/elementin tapahtumaan tehdään on-direktiivin avulla. Direktiivin ja tapahtuman lisäksi voidaan käyttää määreitä () muuttamaan tapahtumankäsittelijän toimintaa syntaksilla <button> on:click|once|stopPropagation|preventDefault={handleClick}>...</button>. Tapahtumankäsittelijä voi olla yksinkertaisen funktion sijasta myös ns. tapahtumanlähettäjä (), jonka luomiseen käytetään Svelten createEventDispatcher-funktiota. Omien tapahtumien käsittelemiseksi tarvitaan oma ns. toimintofunktio (), joka liitetään elementtiin use-direktiivillä, kuten <div use:toiminto={{...}} on:tapahtuma={...}>...</div>.

Tapahtumat eivät nouse () komponenttihierarkiassa ylös automaattisesti; ulompaan komponenttiin ei kuitenkaan tarvitse määritellä omaa edelleenlähetystä vaan pelkän attribuutin lisääminen riittää <button on:click> ...</button>.

Elinkaari ja siirtymät 

Svelten elinkaarifunktio onMount mahdollistaa JavaScriptin ajon, kun komponentti renderöidään ensimmäisen kerran. Muita elinkaarifunktioita ovat onDestroy, beforeUpdate, afterUpdate ja tick (esim. await tick(); teeJotain();.

Animaatioiden tekemiseen löytyy työkaluja motion, easing, transition ja animate moduuleista, kuten tweened, spring, fade, crossfade ja flip. DOM-siirtymät sidotaan elementteihin transition-, in-, out ja animate-direktiivien avulla, kuten <p transition:fly="{{parametri: 10 }}">...</p>. Siirtymillä voi olla myös määreitä, kuten transition:slide|local.

Lähteet 

Ohjelmointikielet