Svelte offre une flexibilité remarquable pour créer des composants dynamiques. Dans ce tutoriel, nous allons explorer comment instancier des composants à la volée et leur transmettre des propriétés de manière élégante et efficace.
Les bases des composants dynamiques
<script>
import Foo from "./Foo.svelte";
import Bar from "./Bar.svelte";
let actual = Foo;
</script>
<svelte:component this={actual} on:click={()=>actual=Bar} />
Dans ce simple exemple, on importe 2 composants Foo et Bar.
Puis on crée une variable actual
dans laquelle on va mettre le composant en cours, en l’occurrence Foo
.
Svelte propose la balise spéciale <svelte:component>
qui permet de créer des composants à la volée.
On lui indique dans la propriété this
le composant à afficher, dans notre exemple, actual
.
À titre de démonstration, on ajoute un événement on:click
pour changer le composant en Bar
simplement en modifiant la variable actual
.
Svelte se charge d’afficher le composant en substituant Bar
à Foo
.
Transmettre des paramètres (props)
Un point clé est la capacité de passer des paramètres aux composants dynamiques. Pour un composant classique, on peut écrire :
<Foo age=22 />
On affecte la valeur 22 à la propriété age
.
Pour un composant dynamique, c’est pareil :
<svelte:component this={Foo} age=22 />
Mais imaginons que notre second composant Bar
accepte 2 paramètres :
<Bar age=572 name="Da Vinci" />
Notre composant dynamique devra s’écrire :
<svelte:component this={Bar} age=572 name="Da Vinci" />
Et là, on a un problème. Comment les gérer dans le composant dynamique tout en leur passant le bon nombre de paramètres ?
Ma technique consiste à encapsuler le composant avec ses propriétés dans un objet et à utiliser le spread operator
{...props}
.
Par exemple, pour le composant Foo
, j’écrirai un objet FooCmp
:
<script>
let FooCmp = {
cmp: Foo,
props: {
age: 42
}
}
let actual = FooCmp;
</script>
<svelte:component
this={actual.cmp}
{...actual.props}
/>
Voici l’exemple complet, avec l’utilisation des 2 composants et une fonction
flip
qui permet de les intervertir.
App.svelte
<script>
import Foo from "./Foo.svelte";
import Bar from "./Bar.svelte";
let FooCmp = {
cmp: Foo,
props: {
age: 42
}
};
let BarCmp = {
cmp: Bar,
props: {
age: 572,
name: "Da Vinci"
}
};
let actual = FooCmp;
let flip = () => actual = actual.cmp == Foo ? BarCmp : FooCmp;
</script>
<svelte:component
this={actual.cmp}
on:click={flip}
{...actual.props}
/>
Chacun des composants importés va afficher ses propriétés dans un bouton, et activer l’événement on:click
.
Foo.svelte
<script>
export let age = 0;
</script>
<button on:click>Foo {age}</button>
Bar.svelte
<script>
export let name = "";
export let age = 0;
</script>
<button on:click>Bar {name} {age}</button>
Remarquez qu’on ne fait que transmettre l’événement on:click
car il n’est pas traité ici, mais au niveau du parent, le composant dynamique.
Conclusion
Vous pouvez facilement instancier et manipuler des composants à la volée avec <svelte:component>
. Svelte offre une approche simple et puissante pour créer des composants dynamiques.
Et JavaScript nous fournit tous les outils pour pouvoir contourner le problème du nombre de props différents par composant.
N’hésitez pas à expérimenter et à adapter cette approche à vos propres besoins !