Bonnes pratiques
Ce document met en lumière certaines bonnes pratiques qui vous aideront à
écrire des applications Svelte rapides et robustes. Il est également disponible
en tant que skill svelte-core-bestpractices pour vos agents.
$state
Utilisez uniquement la rune $state pour des variables qui ont besoin d'être
réactives — en d'autres mots, pour des variables qui peuvent provoquer la
mise à jour d'un $effect, d'un $derived ou d'expressions de templates. Tout
le reste peut être une variable normale.
Les tableaux et les objets ($state({...}) ou $state([...])) sont rendus profondément réactifs,
ce qui signifie que leur mutation va déclencher des mises à jour. Ceci a une contrepartie : en
échange d'une réactivité fine, les objets doivent être transformés en proxies, ce qui implique un
surcoût en performances. Dans les cas où vous travaillez sur de gros objets qui ne sont que
réassignés (plutôt que mutés), utilisez plutôt $state.raw. C'est souvent le cas avec les réponses
d'API, par exemple.
$derived
Pour calculer quelque chose depuis un état, utilisez $derived plutôt que $effect :
// faites ceci
let square = function $derived<number>(expression: number): number
namespace $derived
Declares derived state, i.e. one that depends on other state variables.
The expression inside $derived(...) should be free of side-effects.
Example:
let double = $derived(count * 2);
$derived(let num: numbernum * let num: numbernum);
// ne faites pas ceci
let square;
function $effect(fn: () => void | (() => void)): void
namespace $effect
Runs code when a component is mounted to the DOM, and then whenever its dependencies change, i.e. $state or $derived values.
The timing of the execution is after the DOM has been updated.
Example:
$effect(() => console.log('The count is now ' + count));
If you return a function from the effect, it will be called right before the effect is run again, or when the component is unmounted.
Does not run during server-side rendering.
$effect(() => {
let square: numbersquare = let num: numbernum * let num: numbernum;
});On fournit à
$derivedune expression, et pas une fonction. Si vous devez utiliser une fonction (car l'expression est complexe, par exemple), utilisez$derived.by.
Les dérivées sont modifiables — vous pouvez leur assigner des valeurs, comme avec $state, mais
elles seront ré-évaluées lorsque leur expression sera mise mise à jour.
Si l'expression dérivée est un objet ou un tableau, celui-ci sera renvoyé tel quel — il ne sera
pas rendu profondément réactif. Vous pouvez toutefois utilisez $state dans $derived.by dans
les rares cas où vous en auriez besoin.
$effect
Les effets sont un outil de dernier recours et devraient être évités si possible. En particulier, évitez de mettre à jour un état dans un effet.
- Si vous avez besoin de vous synchroniser avec une librairie externe comme D3, il est souvent plus
simple d'utiliser
{@attach ...} - Si vous avez besoin d'exécuter du code en réponse à une interaction utilisateur, mettez le code directement dans un gestionnaire d'évènement ou utilisez une liaison de fonction, selon ce qui est le plus approprié
- Si vous avez besoin de logguer des valeurs pour déboguer, utiliser
$inspect - Si vous avez besoin d'observer quelque chose d'externe à Svelte, utilisez
createSubscriber
N'entourez jamais le contenu d'un effet avec if (browser) {...} ou similaire — les effets ne sont
jamais exécutés sur le serveur.
$props
Traitez les props comme si elles ne changeaient jamais. Par exemple, les valeurs qui dépendent de
props devraient en général être des $derived :
let { let type: anytype } = function $props(): any
namespace $props
Declares the props that a component accepts. Example:
let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();
$props();
// faites ceci
let color = function $derived<"red" | "green">(expression: "red" | "green"): "red" | "green"
namespace $derived
Declares derived state, i.e. one that depends on other state variables.
The expression inside $derived(...) should be free of side-effects.
Example:
let double = $derived(count * 2);
$derived(let type: anytype === 'danger' ? 'red' : 'green');
// ne faites pas ceci — `color` ne sera jamais mise à jour si `type` change
let color = let type: anytype === 'danger' ? 'red' : 'green';
$inspect.trace
$inspect.trace est un outil de déboguage pour la réactivité. Si quelque chose ne se met pas
correctement à jour ou est exécuté plus souvent que nécessaire, vous pouvez ajouter
$inspect.trace(label) en tant que première ligne d'un $effect ou d'un $derived.by (ou de
n'importe quelle fonction appelée par l'un d'eux) pour tracer leurs dépendances et trouver lequel
déclenche une mise à jour.
Évènements
Tout attribut d'élément commençant par on est traité comme un gestionnaire d'évènement :
<button onclick={() => {...}}>click me</button>
<!-- les raccourcis d'attributs fonctionnent également -->
<button {onclick}>...</button>
<!-- ainsi que le spread d'attribut -->
<button {...props}>...</button>Si vous avez besoin d'attacher des gestionnaires à window ou document vous pouvez utiliser
<svelte:window> et <svelte:document> :
<svelte:window onkeydown={...} />
<svelte:document onvisibilitychange={...} />Évitez d'utiliser onMount ou $effect pour faire cela.
Snippets
Snippets sont une manière de définir des morceaux de markup réutilisables pouvant être
instanciés avec la balise {@render ...}, ou passés en tant que props de composants. Ils
doivent être déclarés au sein du template.
{#snippet greeting(name)}
<p>bonjour {name} !</p>
{/snippet}
{@render greeting('tout le monde')}Les snippets déclarés à la racine d'un composant (c-à-d pas dans des éléments ou des blocs) peuvent être référencés au sein d'un
<script>. Un snippet qui ne référence pas un état de composant est également disponible dans<script module>, et peut ainsi être exporté pour être utilisé par d'autres composants.
Blocs each
Privilégiez l'usage de blocs each à clé — ceci améliore les performances en permettant à Svelte d'insérer ou de supprimer des éléments chirurgicalement plutôt que de mettre à jour le DOM d'éléments déjà existants.
La clé doit identifier de manière unique l'objet. N'utilisez pas l'indice de boucle comme clé.
Évitez de déstructurer si vous avez besoin de muter l'élément (avec quelque chose comme
bind:value={item.count} par exemple).
Utiliser des variables Javascript dans le CSS
Si vous avez une variable JS que vous souhaitez utiliser dans votre CSS, vous pouvez définir une
propriété CSS personnalisée avec la directive style:.
<div style:--columns={columns}>...</div>Vous pouvez alors référencer var(--columns) dans la balise <style> du composant.
Styliser les composants enfant
Le CSS de la balise <style> d'un composant est scopé à ce composant. Si un composant parent a
besoin de contrôler les styles d'un enfant, la manière recommandée est d'utiliser des propriétés CSS
personnalisées :
<!-- Parent.svelte -->
<Child --color="red" />
<!-- Child.svelte -->
<h1>Bonjour</h1>
<style>
h1 {
color: var(--color);
}
</style>Si ceci n'est pas possible (par exemple, le composant enfant vient d'une librairie), vous pouvez
utiliser :global pour écraser les styles :
<div>
<Child />
</div>
<style>
div :global {
h1 {
color: red;
}
}
</style>Contexte
Envisagez l'usage du contexte plutôt que de déclarer un état dans un module partagé. Ceci va scoper l'état à la partie de l'application qui en a besoin, et éliminer la possibilité que celui "fuite" entre les utilisateurs lors du rendu côté serveur.
Utilisez createContext plutôt que setContext et getContext, car cette méthode fournit du
typage.
Svelte asynchrone
Si vous utilisez la version 5.36 ou supérieur, vous pouvez utiliser les expressions
await et les hydratables pour utiliser les promesses directement
dans vos composants. Notez que ces expressions nécessitent d'avoir activé l'option
experimental.async dans le fichier de configuration svelte.config.js, car elles ne sont pas
encore considérées comme parfaitement stables.
Évitez l'usage de fonctionnalités dépréciées
Utilisez systématiquement le mode runes pour du nouveau code, et évitez les fonctionnalités qui ont un équivalent plus moderne :
- utilisez
$stateplutôt que la réactivité implicite (par ex.let count = 0; count += 1) - utilisez
$derivedet$effectplutôt que les assignations et déclarations$:(mais n'utilisez les effets que lorsqu'il n'y a pas de meilleure solution) - utilisez
$propsplutôt queexport let,$$propset$$restProps - utilisez
onclick={...}plutôt queon:click={...} - utilisez
{#snippet ...}et{@render ...}plutôt que<slot>,$$slotset<svelte:fragment> - utilisez
<DynamicComponent>plutôt que<svelte:component this={DynamicComponent}> - utilisez
import Self from './ThisComponent.svelte'et<Self>plutôt que<svelte:self> - utilisez les classes avec des champs
$statepour partager des comportements réactifs entre composants plutôt qu'utiliser des stores - utilisez
{@attach ...}plutôt queuse:action - utilsez les tableaux et objets à la manière de
clsxdans les attributsclassplutôt que la directiveclass:
Modifier cette page sur Github llms.txt