Svelte est un cadre d'interface utilisateur relativement nouveau développé par Rich Harris , qui est également l'auteur du constructeur Rollup. Très probablement, Svelte semblera complètement différent de ce que vous avez traité auparavant, mais c'est peut-être même bon. Les deux caractéristiques les plus impressionnantes de ce cadre sont la rapidité et la simplicité. Dans cet article, nous nous concentrerons sur le second.

Étant donné que mon expérience de développement principale est liée à Angular, il est naturel que j'essaie d'apprendre Svelte en copiant les approches qui me sont déjà familières. Et c'est exactement de cela que parlera cet article: comment faire les mêmes choses dans Svelte que dans Angular.
Remarque: Malgré le fait que dans certains cas, j'exprimerai ma préférence, l'article n'est pas une comparaison de cadres. Il s'agit d'une introduction rapide et facile à Svelte pour les personnes qui utilisent déjà Angular comme cadre principal.
Spoiler d'avertissement: Svelte est amusant.
Composants
Dans Svelte, chaque composant est associé au fichier où il est écrit. Par exemple, le composant Button
sera créé en nommant le fichier Button.svelte
. Bien sûr, nous faisons généralement la même chose dans Angular, mais avec nous, c'est juste une convention. (Dans Svelte, le nom du composant à importer peut également ne pas coïncider avec le nom du fichier - note du traducteur)
Les composants Svelte sont à fichier unique et se composent de 3 sections: script
, style
et modèle qui n'ont pas besoin d'être enveloppés dans une balise spéciale.
Créons un composant très simple qui montre "Hello World".

Importer des composants
En général, cela revient à importer un fichier JS, mais avec quelques mises en garde:
- vous devez spécifier explicitement l'
.svelte
fichier du composant .svelte
- les composants sont importés à l'intérieur de la
<script>
<script> import Todo from './Todo.svelte'; </script> <Todo></Todo>
À partir des extraits ci-dessus, il est évident que le nombre de lignes pour créer un composant dans Svelte est incroyablement petit. Bien sûr, il y a des implicitités et des limites, mais en même temps, tout est assez simple pour s'y habituer rapidement.
Syntaxe de base
Interpolation
Les interpolations dans Svelte sont plus similaires à celles de React que de Vue ou Angular:
<script> let someFunction = () => {...} </script> <span>{ 3 + 5 }</span> <span>{ someFunction() }</span> <span>{ someFunction() ? 0 : 1 }</span>
J'ai l'habitude d'utiliser des accolades doubles, donc je suis parfois scellé, mais je n'ai peut-être que ce problème.
Attributs
La transmission d'attributs aux composants est également assez simple. Les guillemets sont facultatifs et toutes les expressions Javascript peuvent être utilisées:
//Svelte <script> let isFormValid = true; </script> <button disabled={!isFormValid}></button>
Les événements
La syntaxe des gestionnaires d'événements est: on:={}
.
<script> const onChange = (e) => console.log(e); </script> <input on:input={onChange} />
Contrairement à Angular, nous n'avons pas besoin d'utiliser de parenthèses après le nom de la fonction pour l'appeler. Si vous devez passer des arguments au gestionnaire, utilisez simplement la fonction anonyme:
<input on:input={(e) => onChange(e, 'a')} />
Mon avis sur la lisibilité d'un tel code:
- Nous devons imprimer moins, car nous n'avons pas besoin de guillemets et de crochets - c'est bien quand même.
- Lisez plus fort. J'ai toujours aimé l'approche angulaire plutôt que React, donc pour moi et Svelte c'est plus difficile à prendre. Mais c'est juste mon habitude et mon opinion est quelque peu biaisée.
Directives structurelles
Contrairement aux directives structurées dans Vue et Angular, Svelte propose une syntaxe spéciale pour les boucles et les branches à l'intérieur des modèles:
{#if todos.length === 0} {:else} {#each todos as todo} <Todo {todo} /> {/each} {/if}
J'aime vraiment ça. Aucun élément HTML supplémentaire n'est nécessaire, et en termes de lisibilité, cela semble incroyable. Malheureusement, le symbole #
dans la disposition du clavier britannique de mon Macbook est dans un endroit inaccessible, ce qui affecte négativement mon expérience avec ces structures.
Propriétés d'entrée
La définition des propriétés pouvant être transmises à un composant (analogue à @Input
dans Angular) est aussi simple que d'exporter une variable à partir d'un module JS à l'aide du mot-clé export
. Au début, cela peut être déroutant - mais écrivons un exemple et voyons à quel point c'est simple:
<script> export let todo = { name: '', done: false }; </script> <p> { todo.name } { todo.done ? '✓' : '✕' } </p>
- Comme vous pouvez le voir, nous avons initialisé la propriété
todo
avec la valeur: ce sera la valeur de la propriété par défaut, au cas où elle ne serait pas passée du composant parent
Créez maintenant un conteneur pour ce composant, qui lui transmettra des données:
<script> import Todo from './Todo.svelte'; const todos = [{ name: " Svelte", done: false }, { name: " Vue", done: false }]; </script> {#each todos as todo} <Todo todo={todo}></Todo> {/each}
Semblable aux champs d'un objet JS normal, todo={todo}
peut être raccourci et réécrit comme suit:
<Todo {todo}></Todo>
Au début, cela me semblait étrange, mais maintenant je pense que c'est génial.
Propriétés de sortie
Pour implémenter le comportement de la directive @Output
, par exemple, lorsque le composant parent @Output
des notifications de l'enfant, nous utiliserons la fonction createEventDispatcher
disponible dans Svelte.
- Importez la fonction
createEventDispatcher
et affectez sa valeur de retour à la variable de dispatch
- La fonction de
dispatch
a deux paramètres: le nom de l'événement et les données (qui tomberont dans le champ de detail
de l'objet événement) - Nous
markDone
dispatch
à l'intérieur de la fonction markDone
, qui est appelée par l'événement click ( on:click
)
<script> import { createEventDispatcher } from 'svelte'; export let todo; const dispatch = createEventDispatcher(); function markDone() { dispatch('done', todo.name); } </script> <p> { todo.name } { todo.done ? '✓' : '✕' } <button on:click={markDone}></button> </p>
Dans le composant parent, vous devez créer un gestionnaire pour l'événement done
afin de pouvoir marquer les objets nécessaires dans le tableau des todo
.
- Créer la fonction
onDone
- Nous affectons cette fonction au gestionnaire d'événements appelé dans le composant enfant, comme suit:
on:done={onDone}
<script> import Todo from './Todo.svelte'; let todos = [{ name: " Svelte", done: false }, { name: " Vue", done: false }]; function onDone(event) { const name = event.detail; todos = todos.map((todo) => { return todo.name === name ? {...todo, done: true} : todo; }); } </script> {#each todos as todo} <Todo {todo} on:done={onDone}></Todo> {/each}
Remarque: pour déclencher la détection d'un changement dans un objet, nous ne modifions pas l'objet lui-même. Au lieu de cela, nous attribuons à la variable todos
un nouveau tableau, où l'objet de la tâche souhaitée sera déjà changé en terminé.
Par conséquent, Svelte est considéré comme vraiment réactif : avec l'affectation habituelle d'une valeur à une variable, la partie correspondante de la représentation changera également.
ngModel
Svelte a une syntaxe de bind:<>={}
spéciale bind:<>={}
pour lier des variables spécifiques aux attributs d'un composant et les synchroniser entre elles.
En d'autres termes, il vous permet d'organiser une liaison de données bidirectionnelle:
<script> let name = ""; let description = ""; function submit(e) { </script> <form on:submit={submit}> <div> <input placeholder="" bind:value={name} /> </div> <div> <input placeholder="" bind:value={description} /> </div> <button> </button> </form>
Expressions réactives
Comme nous l'avons vu précédemment, Svelte répond à l'attribution de valeurs aux variables et redessine la vue. Vous pouvez également utiliser des expressions réactives pour répondre aux modifications de la valeur d'une variable et mettre à jour la valeur d'une autre.
Par exemple, créons une variable qui devrait nous montrer que dans le tableau todos
toutes les tâches sont marquées comme terminées:
let allDone = todos.every(({ done }) => done);
Toutefois, la vue ne sera pas redessinée lorsque le tableau est mis à jour, car la valeur de la variable allDone
affectée qu'une seule fois. Nous utiliserons une expression réactive, qui en même temps nous rappellera l'existence de "labels" en Javascript:
$: allDone = todos.every(({ done }) => done);
Ça a l'air très exotique. S'il vous semble qu'il y a «trop de magie», je vous rappelle que les tags sont du Javascript valide .
Une petite démo expliquant ce qui précède:

Injection de contenu
Pour incorporer du contenu, des emplacements sont également utilisés qui sont placés au bon endroit à l'intérieur du composant.
Pour afficher simplement le contenu qui a été transféré à l'intérieur de l'élément composant, un élément slot
spécial est utilisé:
// Button.svelte <script> export let type; </script> <button class.type={type}> <slot></slot> </button> // App.svelte <script> import Button from './Button.svelte'; </script> <Button> </Button>
Dans ce cas, la ligne ""
prendra la place de l'élément <slot></slot>
.
Les emplacements nommés devront être nommés:
// Modal.svelte <div class='modal'> <div class="modal-header"> <slot name="header"></slot> </div> <div class="modal-body"> <slot name="body"></slot> </div> </div> // App.svelte <script> import Modal from './Modal.svelte'; </script> <Modal> <div slot="header"> </div> <div slot="body"> </div> </Modal>
Crochets de cycle de vie
Svelte propose 4 crochets de cycle de vie qui sont importés du package svelte
.
- onMount - appelé lorsqu'un composant est monté dans le DOM
- beforeUpdate - appelé avant la mise à jour du composant
- afterUpdate - appelé après la mise à jour du composant
- onDestroy - appelé lorsqu'un composant est supprimé du DOM
La fonction onMount
prend en paramètre une fonction de rappel qui sera appelée lorsque le composant sera placé dans le DOM. Autrement dit, il est similaire à l' ngOnInit
crochet ngOnInit
.
Si la fonction de rappel renvoie une autre fonction, elle sera appelée lorsque le composant sera supprimé du DOM.
<script> import { onMount, beforeUpdate, afterUpdate, onDestroy } from 'svelte'; onMount(() => console.log('', todo)); afterUpdate(() => console.log('', todo)); beforeUpdate(() => console.log(' ', todo)); onDestroy(() => console.log('', todo)); </script>
Il est important de se rappeler que lors de l'appel à onMount
toutes les propriétés qui y sont incluses doivent déjà être initialisées. Autrement dit, dans le fragment ci-dessus, les todo
doivent déjà exister.
Gestion de l'État
La gestion de votre état à Svelte est incroyablement simple, et peut-être que cette partie du cadre me sympathise plus que quiconque. Vous pouvez oublier la verbosité du code lorsque vous utilisez Redux. Par exemple, nous allons créer du stockage dans notre application pour le stockage et la gestion des tâches.
Voûtes enregistrables
Vous devez d'abord importer l' writable
de stockage writable
partir du package svelte/store
et lui indiquer la valeur initiale initialState
import { writable } from 'svelte/store'; const initialState = [{ name: " Svelte", done: false }, { name: " Vue", done: false }]; const todos = writable(initialState);
Habituellement, je mets du code similaire dans un fichier séparé comme todos.store.js
et todos.store.js
exporte la variable de stockage afin que le composant où je l'importe puisse fonctionner avec.
De toute évidence, l'objet todos
est devenu un référentiel et n'est plus un tableau. Pour obtenir la valeur de stockage, nous allons utiliser un peu de magie dans Svelte:
- En ajoutant le caractère
$
au nom de la variable de stockage, nous obtenons un accès direct à sa valeur!
Ainsi, nous remplaçons simplement dans le code toutes les références à la variable todos
par $todos
:
{#each $todos as todo} <Todo todo={todo} on:done={onDone}></Todo> {/each}
Réglage de l'état
La nouvelle valeur du stockage enregistrable peut être spécifiée en appelant la méthode set
, qui change impérativement l'état en fonction de la valeur transmise:
const todos = writable(initialState); function removeAll() { todos.set([]); }
Mise à jour du statut
Pour mettre à jour le stockage (dans notre cas, todos
), en fonction de son état actuel, vous devez appeler la méthode de update
et lui passer une fonction de rappel qui renverra le nouvel état du stockage.
Nous onDone
fonction onDone
que nous avons créée précédemment:
function onDone(event) { const name = event.detail; todos.update((state) => { return state.map((todo) => { return todo.name === name ? {...todo, done: true} : todo; }); }); }
Ici, j'ai utilisé un réducteur directement dans le composant, ce qui est une mauvaise pratique. Nous le déplaçons dans un fichier avec notre référentiel et en exportons une fonction qui mettra simplement à jour l'état.
Abonnement au changement de statut
Afin de découvrir que la valeur dans le référentiel a changé, vous pouvez utiliser la méthode d' subscribe
. Gardez à l'esprit que le référentiel n'est pas un objet observable
, mais fournit une interface similaire.
const subscription = todos.subscribe(console.log); subscription();
Observables
Si cette partie vous a causé le plus d'enthousiasme, alors je m'empresse de plaire qu'il n'y a pas si longtemps, le support RxJS a été ajouté à Svelte et l'Observable pour ECMAScript a été introduit.
En tant que développeur Angular, je suis déjà habitué à travailler avec une programmation réactive, et l'absence d'un équivalent de canal asynchrone serait extrêmement gênant. Mais Svelte m'a aussi surpris ici.
Voyons un exemple de la façon dont ces outils fonctionnent ensemble: afficher une liste de référentiels sur Github, trouvée par le mot-clé "Svelte"
.
Vous pouvez copier le code ci-dessous et l'exécuter directement dans le REPL :
<script> import rx from "https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"; const { pluck, startWith } = rx.operators; const ajax = rx.ajax.ajax; const URL = `https://api.github.com/search/repositories?q=Svelte`; const repos$ = ajax(URL).pipe( pluck("response"), pluck("items"), startWith([]) ); </script> {#each $repos$ as repo} <div> <a href="{repo.url}">{repo.name}</a> </div> {/each}
Ajoutez simplement le symbole $
au nom de la variable observable repos$
et Svelte affichera automatiquement son contenu.
Ma liste de souhaits pour Svelte
Support typographique
En tant que passionné de Typescript, je ne peux m'empêcher de souhaiter la possibilité d'utiliser des types dans Svelte. J'y suis tellement habitué que parfois je m'emballe et arrange des types dans mon code, que je dois ensuite supprimer. J'espère vraiment que Svelte ajoutera bientôt le support pour Typescript. Je pense que cet article sera sur la liste de souhaits de tous ceux qui souhaitent utiliser Svelte avec une expérience avec Angular.
Accords et directives
Le rendu de la représentation de n'importe quelle variable du bloc <script>
est une fonctionnalité très puissante du framework, mais à mon avis, cela peut conduire à un encombrement de code. J'espère que la communauté Svelte travaillera à travers un certain nombre de conventions et de directives pour aider les développeurs à écrire du code de composant propre et compréhensible.
Soutien communautaire
Svelte est un projet grandiose qui, avec un effort accru de la communauté dans la rédaction de packages tiers, de manuels, d'articles de blog et plus encore, peut décoller et devenir un outil reconnu dans le monde étonnant du développement Frontend que nous avons aujourd'hui.
En conclusion
Malgré le fait que je n'étais pas fan de la version précédente du framework, Svelte 3 m'a fait bonne impression. C'est simple, petit, mais peut faire beaucoup. Il est si différent de tout ce qui l'entoure qu'il m'a rappelé l'excitation que j'ai ressentie lorsque je suis passé de jQuery à Angular.
Quel que soit le framework que vous utilisez actuellement, l'apprentissage de Svelte ne prendra probablement que quelques heures. Une fois que vous aurez appris les bases et compris les différences avec ce que vous avez l'habitude d'écrire, travailler avec Svelte sera très facile.
Dans la chaîne Telegram en langue russe @sveltejs, vous trouverez sûrement des développeurs qui ont de l'expérience avec divers cadres et sont prêts à partager leurs histoires, leurs pensées et leurs conseils concernant Svelte.