Sep 14, 2023-8 MIN READ

Vue.js : Les slots, la clef de la modularité

Explorez les slots Vue.js pour créer des composants flexibles et modulaires. De l'utilisation basique aux scoped slots, découvrez comment maîtriser cette fonctionnalité puissante.

J'ai récemment reparcouru la documentation de Vue.js, et plus précisément la partie qui concerne les slots. Je me suis dit que ce serait une bonne idée d'écrire un article sur le sujet pour partager ce que je savais déjà, mais aussi ce que j'ai nouvellement appris. Alors c'est parti !

Nous avons déjà les composants pour construire notre application à la manière des Lego. Avec les slots, imaginez pouvoir personnaliser chaque partie de l'un de ces composants sans avoir à le dupliquer à chaque fois. Eh bien, c'est possible et c'est plutôt simple à mettre en place !

Dans cet article, nous allons explorer ce mécanisme puissant pour vous montrer comment rendre vos composants plus flexibles !

Slot par défaut

Un slot par défaut est un espace réservé dans votre composant où vous pouvez insérer du contenu personnalisé. Il est défini en utilisant la balise <slot></slot> dans le template de votre composant.

Exemple Simple

Prenons l'exemple d'un composant simple que j'ai nommé Default.

<template>
  <div class="card">
    <slot></slot>
    <div class="card-body">
      Lorem ipsum dolor sit amet consectetur adipisicing elit. Totam, molestias distinctio minus exercitationem
      provident expedita quia asperiores a! Provident optio blanditiis possimus reiciendis corrupti nemo autem, voluptas
      iste minus voluptate.
    </div>
  </div>
</template>

Rien de très compliqué, voici comment utiliser ce composant :

<template>
  <Basic>
    <h1>Slot par défaut</h1>
  </Basic>
</template>

Et le rendu final dans le DOM :

<div class="card">
  <h1>Slot par défaut</h1>
  <div class="card-body">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Totam, molestias distinctio minus exercitationem
      provident expedita quia asperiores a! Provident optio blanditiis possimus reiciendis corrupti nemo autem, voluptas
      iste minus voluptate.
  </div>
</div>

Vous commencez à comprendre ? Ici je n'ai ajouté qu'un <h1></h1>, mais vous pouvez bien évidemment y passer ce que vous souhaitez, même un autre composant !

Fallback content

Le "fallback content" peut s'avérer très utile quand vous souhaitez un contenu par défaut pour vos slots. Ce contenu s'affichera uniquement si le composant parent n'a pas fourni de contenu spécifique pour ce slot :

<button type="submit">
  <slot>
    Submit 
  </slot>
</button>

Si nous voulons que le texte "submit" soit le contenu par défaut du bouton, nous pouvons le placer à l'intérieur des balises <slot></slot>

Les slots nommés

Les slots par défaut sont très utiles, mais ça ne s'arrête pas là. Vue.js va encore plus loin en nous donnant la possibilité d'utiliser des slots nommés.

Un slot nommé est similaire au slot par défaut, à la seule différence qu'il possède un attribut name qui lui permet d'être identifié et ciblé. Cela signifie que vous pouvez avoir plusieurs slots dans un seul et même composant et déterminer exactement où chaque morceau du contenu doit être inséré.

<template>
  <div class="card">
    <slot name="title"></slot>
    <div class="card-body">
      <slot name="content"></slot>
    </div>
  </div>
</template>

Et voici comment on l'utilise :

<Named>
  <template v-slot:title>
    <h1>Slot nommé</h1>
  </template>
  <template v-slot:content>
    <p>
      Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minima repellat vitae, in animi harum alias!
      Magni natus enim numquam perspiciatis deleniti. Sunt dolorum odit, pariatur impedit dolor ullam voluptatibus
      laborum?
    </p>
  </template>
</Named>

Dans le composant parent, vous pouvez cibler chaque slot en utilisant une balise <template></template> et la directive v-slot.

Vous pouvez, à la place d'écrire v-slot, utiliser l'abréviation #, ainsi <template v-slot:title> peut être raccourci en <template #title>.

Avec les slots nommés vous pouvez concevoir des composants comme des "squelettes" avec plusieurs emplacements pour y insérer du contenu. Encore une occasion de rendre votre code plus flexible !

Portée des données dans les slots

Les slots ont des règles spécifiques concernant la portée des données. Le contenu d'un slot est défini dans le composant parent. Prenons un exemple simple :

<span>{{ titleDefault }}</span>
<Default>
  <h1>{{ titleDefault }}</h1>
</Default>

Dans cet exemple, les deux interpolations {{ titleDefault }} ont accès à la même donnée et afficheront le même contenu. Cela signifie que le contenu que vous placez à l'intérieur d'un slot peut utiliser n'importe quelle donnée, méthode ou propriété calculée définie dans le composant parent.

D'accord, c'est pratique. Mais est-il possible de passer de la donnée de l'enfant au parent ? Eh bien vous savez quoi ? C'est possible !

Slots avec portée (Scoped slots)

Les scoped slots sont une fonctionnalité qui permet de passer des données du composant enfant au contenu du slot. Le contenu d'un slot n'a pas accès aux données du composant parent. Cependant, il y a des situations où il serait utile que le contenu d'un slot puisse utiliser des données à la fois du parent et de l'enfant. Comme par exemple :

<div>
  <slot :text="greetingMessage" :count="1"></slot>
</div>

Ici, le composant enfant passe deux propriétés text et count au slot. Ces propriétés peuvent ensuite être utilisées dans le contenu du slot dans le composant parent :

<MyComponent v-slot="slotProps">
  {{ slotProps.text }} {{ slotProps.count }}
</MyComponent>

Les slots nommés peuvent également avoir une portée. Les propriétés passées à un slot nommé sont accessibles comme la valeur de la directive v-slot

<MyComponent>
  <template #header="headerProps">
    {{ headerProps.text }}
  </template>
</MyComponent>

Il est important de noter que si vous mélangez des slots nommés avec le slot par défaut, ayant une portée, vous devez utiliser une balise template explicite pour le slot par défaut :

<template>
  <MyComponent>
    <template #default="{ message }">
      <p>{{ message }}</p>
    </template>

    <template #footer>
      <p>Here's some contact info</p>
    </template>
  </MyComponent>
</template>

Sinon ça entraînera une erreur de compilation.

Noms de slots dynamiques

Avec Vue.js, il est possible d'utiliser des arguments de directive dynamique avec v-slot ce qui permet de définir des noms de slots dynamiquement.

Supposons que nous ayons un composant <base-layout></base-layout> et que nous voulions définir le nom du slot en fonction d'une variable ou d'une propriété. Nous pouvons utiliser la syntaxe v-slot:[dynamicSlotName] pour le faire, par exemple :

<base-layout>
  <template v-slot:[dynamicSlotName]>
    ... <!-- Contenu du slot -->
  </template>
</base-layout>

Et comme expliqué précédemment, nous pouvons utiliser l'abréviation # :

<base-layout>
  <template #[dynamicSlotName]>
    ... <!-- Contenu du slot -->
  </template>
</base-layout>

Conclusion

En conclusion, les slots sont un excellent outil pour rendre vos composants plus flexibles. Ils vous permettent d'insérer du contenu personnalisé dans des parties spécifiques de votre composant sans avoir à le réécrire. Que ce soit pour des boutons, des titres, ou même d'autres composants, les slots simplifient le processus et rendent votre code plus propre. Alors n'hésitez pas à en abuser!

© 2025 Jordan Bastin.