Andrea "Kiraya"Magini

IT Professional Master

Single post

Svelte Framework Tutorial myTodoList

Uscito da molto, ma passato inosservato ai più, con la release 3, Svelte torna prepotentemente nella lotta tra i framework di Frontend, insieme ad Angular, React e Vue.

Viste le continue perdite di performance di Angular, e l’ascesa di Vue, Svelte con questa nuova release, riprende nuova linfa, riprendendo React e si colloca ai vertici dei framework, nonostante la scarsità di librerie e wrapper verso componentistica UI.

Uno dei punti di vantaggio di Svelte, é quello di riuscire ad assicurare le stesse performance (se non migliori) di React mantenendo una sintassi puramente html e javascript e senza utilizzare un virtual Dom.

In questo articolo https://svelte.dev/blog/virtual-dom-is-pure-overhead viene spiegato accuratamente come si comporta un virtualDom e perché essendo un overhead sopra il dom nativo, sia per forza di cose più lento, da qui il famoso meme “it’s faster because is slow”.

Prerequisiti e Installazione

Prerequisito del tutorial, la presenza sulla nostra macchina di Node.JS e di Npm.

Per installare Svelte localmente, partendo da un template-app di default:

npx degit sveltejs/template mytodolist-app
cd mytodolist-app
npm install

--per eseguire localmente
npm run dev

--per buildare in production mode(versione ottimizzata di release)
npm run build

La prima cosa che notiamo é che i componenti di Svelte sono tutti contenuti in file .svelte che contengono sia la logica che il markup che gli stili.

Svelte infatti non necessita obbligatoriamente  di css esterni, ma include gli stili direttamente nei sorgenti.

Per semplicità metteremo gli stili di default nel global.css della cartella public, e specializzeremo il css nella view.

Questa la pagina di default generata:

<script>
export let name;
</script>

<main>
<h1>Hello {name}!</h1>
<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>

<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}

h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
}

@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>

Cominciamo a definire la struttura dell’apps

Modifichiamo il nostro Svelto.app per andare a descrivere la nostra form, qualche attributo css e UL per mantenere l’elenco dei todo:

<script>
export let name;
</script>

<main>
<div class="container">
<h1 class="title">{name}</h1>
<ul class="todos">
</ul>
<div>
<h2>Inserisci un nuovo ToDo</h2>
<p>Cosa dovresti fare oggi?</p>
</div>
<form>
<input class="todo_input" type="text" aria-label="Inserisci cosa devi fare" placeholder="ad esempio creare un css"/>
</form>
</div>
</main>

<style>

main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
background-color: black;
color: white;

}

h1 {
text-transform: uppercase;
font-size: 2em;
font-weight: 100;
}

@media (min-width: 640px) {
main {
max-width: none;
}
}

addTodo

Aggiungiamo una funzione per l’inserimento di un todo, e agghianciamolo alla submit della form prevenendo il refresh della pagina ad ogni submit:

<script>
export let name;

let todos = [];
let todoText ='';

function addNewTodo(){
if (!todoText.trim()){
return;
}

const item ={
text:todoText,
done:false,
date: Date.now()
};

todos =[...todos,item];
todoText='';
}

</script>

<main>
<div class="container">
<h1 class="title">{name}</h1>
<ul class="todos">
</ul>
<div>
<h2>Inserisci un nuovo ToDo</h2>
<p>Cosa dovresti fare oggi?</p>
</div>
<form on:submit|preventDefault={addNewTodo}>
<input class="todo_input" type="text" bind:value={todoText} aria-label="Inserisci cosa devi fare" placeholder="ad esempio creare un css"/>
</form>
</div>
</main>

Rappresentiamo la lista dei Todo

Con un semplice costrutto foreach definiamo la visualizzazione dell’elenco dei todo:

<ul class="todos">
{#each todos as todo (todo.date)}
<li class="todo-item">
<input id={todo.date} type="checkbox" />
<label for={todo.date} ></label>
<span>{todo.text}</span>
</li>
{/each}
</ul>

L’app finale risulta questa:

<script>
export let name;

let todos = [];
let todoText ='';

function addNewTodo(){
if (!todoText.trim()){
return;
}

const item ={
text:todoText,
done:false,
date: Date.now()
};

todos =[...todos,item];
todoText='';
}

</script>

<main>
<div class="container">
<h1 class="title">{name}</h1>
<ul class="todos">
{#each todos as todo (todo.date)}
<li class="todo-item">
<input id={todo.date} type="checkbox" />
<label for={todo.date} ></label>
<span>{todo.text}</span>
</li>
{/each}
</ul>
<div>
<h2>Inserisci un nuovo ToDo</h2>
<p>Cosa dovresti fare oggi?</p>
</div>
<form on:submit|preventDefault={addNewTodo}>
<input class="todo_input" type="text" bind:value={todoText} aria-label="Inserisci cosa devi fare" placeholder="ad esempio creare un css"/>
</form>
</div>
</main>

<style>

.container {
text-align: center;
padding: 1em;
max-width: 500px;
margin: 0 auto;
background-color: black;
color: white;
overflow-y:auto;

}

h1 {
text-transform: uppercase;
font-size: 2em;
font-weight: 100;
}

.todos {
list-style: none;
margin-bottom: 20px;
}

.todo-item {
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
}

@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>

Per divertimento, provate ad aggiungere il toggle del todo finito, la rimozione dei todo, e il riordino della lista sulla base di quelli eseguiti.