Svelte

Quick start

npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
Svelte converts your app into ideal JavaScript at build time, rather than interpreting your application code at run time. This means you don't pay the performance cost of the framework's abstractions, and you don't incur a penalty when your app first loads.
  • self-contained using components
  • for small apps, fast and light-weight

Basic concepts

# development 
npm run dev

# production 
npm run build
npm run start

dynamic attributes

<script>
let src = 'tutorial/image.gif';
let name = 'rick'
</script>

<img src={src} alt='{name} roll’>
<img {src} alt='{name} roll'>

styling and nesting

<style>
p {
color: purple;
font-family: 'Comic Sans MS', cursive;
font-size: 2em;
}
</style>
<script>
import Nested from './Nested.svelte';
</script>
<p>This is a paragraph.</p>
<Nested/>

This is a paragraph.

This is another paragraph (no style).

special tags

# use @html tag to render HTML directly into a component

<script>

	let string = `this string contains some <strong>HTML!!!</strong>`;

</script>

<p>{@html string}</p>

import and instantiate to use

import App from './App.svelte';

const app = new App({
	target: document.body,
	props: {
		answer: 42
	}
});

reactive event handler

syncs DOM and state

<script>
	let count = 0;

	function handleClick() {
		// event handler code goes here
		count +=1;
	}
</script>

<button on:click={handleClick}>
	Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
# is a reactive declaration, reruns when referenced values change
$:doubled = count * 2;

arbitrary statements

group and put them in front of IF blocks

	$: if(count >= 10) {
		console.log(`alert = ${count}`)
		alert(`count is high`);
		count = 9;
		
	}

assignment to arrays

pop, shift, unshift and splice similar to push:

<script>
	let numbers = [1, 2, 3, 4];

	function addNumber() {
		numbers.push(numbers.length + 1);
		//not redundant, assign = triggers reactivity
		numbers = numbers;
	}
	
	function addNumberIdiomatic() {
		numbers = [...numbers, numbers.length + 1];
	}

	$: sum = numbers.reduce((t, n) => t + n, 0);
</script>

<p>{numbers.join(' + ')} = {sum}</p>

<button on:click={addNumberIdiomatic}>
	Add a number
</button>

props

use keyword export (not the usual js) in the nested component -- pass data to children

<script>
	export let answer;
    export let misteryanswer;

</script>

// in caller
<Nested answer={42}/>
<Nested/>

conditionals

add to html template via `#if`

{#if user.loggedIn}
<button on:click={toggle}>
	Log out
</button>
{:else}
<button on:click={toggle}>
	Log in
</button>
{/if}

chaining via {:else if 5 > x} block continuation tag

loops

on arrays, array-like objects, and iterables.

{#each cats as cat}
	<li><a target="_blank" href="https://www.youtube.com/watch?v={cat.id}">
	{cat.name}
	</a></li>
{/each}
//access index
{#each cats as cat, index}

//or destructure
each cats as { id, name }

updates in loops, usually affect all elements' state. To avoid unwanted updates use unique identifiers – best to use string or numeral as id, but objects allowed

{#each things as thing (thing.id)}
	<Thing current={thing.color}/>
{/each}

await

directly in the markup via #await – most recent promise is considered = no race conditions

{#await promise}
	<p>...waiting</p>
{:then number}
	<p>The number is {number}</p>
{:catch error}
	<p style="color: red">{error.message}</p>
{/await}

a promise that can't reject and only notifies when the promise has resolved

{#await promise then value}
	<p>the value is {value}</p>
{/await}