Comment implémenter des notifications Toast dans Vue
Vous devez fournir un retour d’information aux utilisateurs—un formulaire enregistré, un appel API échoué, un téléchargement réussi. Les notifications toast résolvent cela élégamment : des messages brefs qui apparaissent, délivrent l’information et disparaissent sans perturber le flux de travail.
Ce guide couvre deux approches pour les notifications toast dans Vue 3 : la construction d’un système personnalisé basé sur des composables et l’intégration de bibliothèques établies comme Vue Toastification ou Notivue. Les deux utilisent les patterns modernes de la Composition API avec la syntaxe <script setup>.
Points clés à retenir
- Un système de toast personnalisé dans Vue 3 nécessite seulement trois éléments : un état réactif partagé, une fonction composable et un composant conteneur basé sur Teleport.
- Les bibliothèques tierces comme Vue Toastification et Notivue gèrent la file d’attente, les animations, l’accessibilité et les thèmes prêts à l’emploi.
- Dans Nuxt 3, les notifications toast nécessitent une exécution côté client uniquement—utilisez des wrappers
<ClientOnly>ou les suffixes de plugin.client.ts. - Les toasts accessibles utilisent des régions
aria-live, des boutons de fermeture avec des labels clairs et respectent les préférencesprefers-reduced-motion.
Construire un système de Toast personnalisé avec les Composables Vue
Un système de notification minimal avec un composable Vue nécessite trois éléments : un état réactif, une fonction composable et un composant rendu utilisant Teleport.
Le Composable Toast
Créez un store réactif partagé accessible par n’importe quel composant :
// composables/useToast.ts
import { ref, readonly } from 'vue'
interface Toast {
id: number
message: string
type: 'success' | 'error' | 'info' | 'warning'
}
const toasts = ref<Toast[]>([])
let id = 0
export function useToast() {
const add = (message: string, type: Toast['type'] = 'info', duration = 3000) => {
const toast = { id: ++id, message, type }
toasts.value.push(toast)
if (duration > 0) {
setTimeout(() => remove(toast.id), duration)
}
}
const remove = (toastId: number) => {
toasts.value = toasts.value.filter(t => t.id !== toastId)
}
return {
toasts: readonly(toasts),
success: (msg: string) => add(msg, 'success'),
error: (msg: string) => add(msg, 'error'),
info: (msg: string) => add(msg, 'info'),
warning: (msg: string) => add(msg, 'warning'),
remove
}
}
La ref toasts est déclarée en dehors de la fonction composable afin que chaque appel à useToast() partage le même tableau réactif. Le wrapper readonly empêche les consommateurs de muter l’état directement—seuls add et remove peuvent modifier la liste.
Le composant conteneur Toast
Affichez les toasts en utilisant Teleport pour les positionner en dehors de votre arbre de composants :
<!-- components/ToastContainer.vue -->
<script setup lang="ts">
import { useToast } from '@/composables/useToast'
const { toasts, remove } = useToast()
</script>
<template>
<Teleport to="body">
<div
class="toast-container"
role="region"
aria-live="polite"
aria-label="Notifications"
>
<div
v-for="toast in toasts"
:key="toast.id"
:class="['toast', `toast--${toast.type}`]"
role="status"
>
{{ toast.message }}
<button @click="remove(toast.id)" aria-label="Fermer la notification">×</button>
</div>
</div>
</Teleport>
</template>
Placez <ToastContainer /> dans votre App.vue, puis appelez useToast() depuis n’importe quel composant pour déclencher des notifications.
Note sur les rôles ARIA : Le conteneur utilise
aria-live="polite"afin que les lecteurs d’écran annoncent les nouveaux toasts sans interrompre l’utilisateur. Les toasts individuels utilisentrole="status"plutôt querole="alert", ce qui s’associe correctement avec la région live polie. Réservezrole="alert"(qui impliquearia-live="assertive") pour les messages d’erreur urgents qui exigent une attention immédiate.
Utiliser des bibliothèques tierces
Pour les applications en production, les bibliothèques maintenues gèrent les cas limites que vous auriez autrement à construire vous-même : gestion de la file d’attente, animations, accessibilité et thématisation.
Configuration de Vue Toastification
Installez et enregistrez le plugin :
// main.ts
import { createApp } from 'vue'
import Toast from 'vue-toastification'
import 'vue-toastification/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(Toast, {
position: 'top-right',
timeout: 5000
})
app.mount('#app')
Utilisez le composable dans les composants :
<script setup>
import { useToast } from 'vue-toastification'
const toast = useToast()
const handleSave = async () => {
try {
await saveData()
toast.success('Modifications enregistrées')
} catch {
toast.error('Échec de l\'enregistrement')
}
}
</script>
Discover how at OpenReplay.com.
Alternative Notivue
Notivue offre une API composable similaire avec des options de personnalisation supplémentaires et des fonctionnalités d’accessibilité intégrées.
Notifications Toast dans Nuxt 3
Les notifications toast dans Nuxt 3 doivent être déclenchées dans des contextes côté client (par exemple, dans des gestionnaires d’événements ou onMounted) car elles manipulent le DOM et ne doivent pas s’exécuter pendant le rendu côté serveur :
<!-- app.vue -->
<template>
<NuxtPage />
<ClientOnly>
<ToastContainer />
</ClientOnly>
</template>
Si vous utilisez Nuxt UI, il fournit son propre composable useToast—aucune bibliothèque supplémentaire n’est nécessaire. Pour d’autres configurations, créez un plugin Nuxt :
// plugins/toast.client.ts
import Toast from 'vue-toastification'
import 'vue-toastification/dist/index.css'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Toast)
})
Le suffixe .client.ts garantit que le plugin ne s’exécute que dans le navigateur.
Considérations d’accessibilité
Les toasts doivent être accessibles aux utilisateurs de lecteurs d’écran :
- Utilisez
aria-live="polite"sur le conteneur de toast afin que les nouveaux messages soient annoncés sans interruption - Fournissez des boutons de fermeture avec des attributs
aria-labeldescriptifs - Respectez
prefers-reduced-motionen désactivant les animations lorsque demandé - Évitez de fermer automatiquement les messages d’erreur—les utilisateurs ont besoin de temps pour les lire et agir en conséquence
@media (prefers-reduced-motion: reduce) {
.toast {
animation: none
}
}
Conclusion
Construisez un système de toast personnalisé lorsque vous avez besoin d’une taille de bundle minimale ou d’un comportement très spécifique. Utilisez Vue Toastification ou Notivue lorsque vous voulez une accessibilité éprouvée, des animations et des options de configuration sans surcharge de maintenance.
Les deux approches fonctionnent dans Vue 3 et Nuxt 3. Le pattern composable garde votre code testable et vos composants découplés de la logique de notification. Commencez avec le composable personnalisé pour comprendre les mécanismes, puis évaluez si une bibliothèque sert mieux les besoins à long terme de votre projet.
FAQ
Oui. Parce que la ref toasts est déclarée en dehors de la fonction useToast au niveau du module, chaque composant qui appelle useToast partage le même état réactif. Cela signifie que n'importe quel composant peut déclencher ou fermer des toasts sans passer de props ou émettre d'événements à travers les composants parents.
Teleport déplace les nœuds DOM du toast vers l'élément body, en dehors de votre hiérarchie de composants. Cela empêche le CSS parent comme overflow hidden ou les contextes d'empilement z-index de rogner ou cacher vos toasts. Cela maintient également le positionnement des toasts cohérent quel que soit l'endroit où le composant conteneur est monté.
Dans le composable personnalisé, passez zéro ou un nombre négatif comme argument de durée pour ignorer l'appel setTimeout. Avec Vue Toastification, définissez timeout à false pour des toasts spécifiques. Les messages d'erreur doivent persister jusqu'à ce que l'utilisateur les ferme manuellement afin qu'ils aient suffisamment de temps pour les lire et réagir.
Oui. Les notifications toast manipulent le DOM, qui n'est pas disponible pendant le rendu côté serveur. Enveloppez votre conteneur de toast dans un composant ClientOnly ou enregistrez votre bibliothèque de toast comme un plugin Nuxt côté client uniquement en utilisant le suffixe de fichier .client.ts. Cela garantit que la logique des toasts ne s'exécute que dans le navigateur.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.