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}