Back

So implementieren Sie Toast-Benachrichtigungen in Vue

So implementieren Sie Toast-Benachrichtigungen in Vue

Sie müssen Benutzern Feedback geben – ein gespeichertes Formular, einen fehlgeschlagenen API-Aufruf, einen erfolgreichen Upload. Toast-Benachrichtigungen lösen dies elegant: kurze Nachrichten, die erscheinen, Informationen liefern und verschwinden, ohne den Arbeitsablauf zu unterbrechen.

Dieser Leitfaden behandelt zwei Ansätze für Vue 3 Toast-Benachrichtigungen: den Aufbau eines benutzerdefinierten Composable-basierten Systems und die Integration etablierter Bibliotheken wie Vue Toastification oder Notivue. Beide verwenden moderne Composition API-Muster mit <script setup>-Syntax.

Wichtigste Erkenntnisse

  • Ein benutzerdefiniertes Toast-System in Vue 3 benötigt nur drei Komponenten: gemeinsamen reaktiven State, eine Composable-Funktion und eine Teleport-basierte Container-Komponente.
  • Drittanbieter-Bibliotheken wie Vue Toastification und Notivue übernehmen Queue-Management, Animationen, Barrierefreiheit und Theming standardmäßig.
  • In Nuxt 3 erfordern Toast-Benachrichtigungen eine clientseitige Ausführung – verwenden Sie <ClientOnly>-Wrapper oder .client.ts-Plugin-Suffixe.
  • Barrierefreie Toasts verwenden aria-live-Regionen, Schließen-Buttons mit klaren Labels und respektieren prefers-reduced-motion-Präferenzen.

Aufbau eines benutzerdefinierten Toast-Systems mit Vue Composables

Ein minimales Vue Composable-Benachrichtigungssystem erfordert drei Komponenten: reaktiven State, eine Composable-Funktion und eine gerenderte Komponente mit Teleport.

Das Toast-Composable

Erstellen Sie einen gemeinsamen reaktiven Store, auf den jede Komponente zugreifen kann:

// 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
  }
}

Die toasts-Ref wird außerhalb der Composable-Funktion deklariert, sodass jeder Aufruf von useToast() dasselbe reaktive Array teilt. Der readonly-Wrapper verhindert, dass Konsumenten den State direkt mutieren – nur add und remove können die Liste modifizieren.

Die Toast-Container-Komponente

Rendern Sie Toasts mit Teleport, um sie außerhalb Ihres Komponentenbaums zu positionieren:

<!-- 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="Dismiss notification">×</button>
      </div>
    </div>
  </Teleport>
</template>

Platzieren Sie <ToastContainer /> in Ihrer App.vue und rufen Sie dann useToast() von jeder Komponente aus auf, um Benachrichtigungen auszulösen.

Hinweis zu ARIA-Rollen: Der Container verwendet aria-live="polite", damit Screenreader neue Toasts ankündigen, ohne den Benutzer zu unterbrechen. Einzelne Toasts verwenden role="status" statt role="alert", was korrekt mit der höflichen Live-Region zusammenpasst. Reservieren Sie role="alert" (was aria-live="assertive" impliziert) für dringende Fehlermeldungen, die sofortige Aufmerksamkeit erfordern.

Verwendung von Drittanbieter-Bibliotheken

Für Produktionsanwendungen übernehmen gepflegte Bibliotheken Randfälle, die Sie sonst selbst entwickeln müssten: Queue-Management, Animationen, Barrierefreiheit und Theming.

Vue Toastification Setup

Installieren und registrieren Sie das 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')

Verwenden Sie das Composable in Komponenten:

<script setup>
import { useToast } from 'vue-toastification'

const toast = useToast()

const handleSave = async () => {
  try {
    await saveData()
    toast.success('Changes saved')
  } catch {
    toast.error('Save failed')
  }
}
</script>

Notivue-Alternative

Notivue bietet eine ähnliche Composable-API mit zusätzlichen Anpassungsoptionen und integrierten Barrierefreiheitsfunktionen.

Toast-Benachrichtigungen in Nuxt 3

Toast-Benachrichtigungen in Nuxt 3 müssen in clientseitigen Kontexten ausgelöst werden (z. B. in Event-Handlern oder onMounted), da sie das DOM manipulieren und nicht während des serverseitigen Renderings ausgeführt werden sollten:

<!-- app.vue -->
<template>
  <NuxtPage />
  <ClientOnly>
    <ToastContainer />
  </ClientOnly>
</template>

Wenn Sie Nuxt UI verwenden, bietet es sein eigenes useToast-Composable – keine zusätzliche Bibliothek erforderlich. Für andere Setups erstellen Sie ein Nuxt-Plugin:

// plugins/toast.client.ts
import Toast from 'vue-toastification'
import 'vue-toastification/dist/index.css'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(Toast)
})

Das .client.ts-Suffix stellt sicher, dass das Plugin nur im Browser ausgeführt wird.

Überlegungen zur Barrierefreiheit

Toasts müssen für Screenreader-Benutzer zugänglich sein:

  • Verwenden Sie aria-live="polite" auf dem Toast-Container, damit neue Nachrichten ohne Unterbrechung angekündigt werden
  • Stellen Sie Schließen-Buttons mit beschreibenden aria-label-Attributen bereit
  • Respektieren Sie prefers-reduced-motion, indem Sie Animationen bei Bedarf deaktivieren
  • Vermeiden Sie automatisches Schließen von Fehlermeldungen – Benutzer benötigen Zeit zum Lesen und Reagieren
@media (prefers-reduced-motion: reduce) {
  .toast {
    animation: none
  }
}

Fazit

Erstellen Sie ein benutzerdefiniertes Toast-System, wenn Sie minimale Bundle-Größe oder hochspezifisches Verhalten benötigen. Verwenden Sie Vue Toastification oder Notivue, wenn Sie bewährte Barrierefreiheit, Animationen und Konfigurationsoptionen ohne Wartungsaufwand wünschen.

Beide Ansätze funktionieren in Vue 3 und Nuxt 3. Das Composable-Muster hält Ihren Code testbar und Ihre Komponenten von der Benachrichtigungslogik entkoppelt. Beginnen Sie mit dem benutzerdefinierten Composable, um die Mechanik zu verstehen, und bewerten Sie dann, ob eine Bibliothek die langfristigen Anforderungen Ihres Projekts besser erfüllt.

FAQs

Ja. Da die toasts-Ref außerhalb der useToast-Funktion auf Modulebene deklariert wird, teilt jede Komponente, die useToast aufruft, denselben reaktiven State. Das bedeutet, dass jede Komponente Toasts auslösen oder schließen kann, ohne Props zu übergeben oder Events durch übergeordnete Komponenten zu emittieren.

Teleport verschiebt die Toast-DOM-Knoten zum body-Element, außerhalb Ihrer Komponentenhierarchie. Dies verhindert, dass übergeordnetes CSS wie overflow hidden oder z-index-Stacking-Kontexte Ihre Toasts abschneiden oder verbergen. Es hält auch die Toast-Positionierung konsistent, unabhängig davon, wo die Container-Komponente gemountet ist.

Im benutzerdefinierten Composable übergeben Sie null oder eine negative Zahl als duration-Argument, um den setTimeout-Aufruf zu überspringen. Bei Vue Toastification setzen Sie timeout für bestimmte Toasts auf false. Fehlermeldungen sollten bestehen bleiben, bis der Benutzer sie manuell schließt, damit er genug Zeit zum Lesen und Reagieren hat.

Ja. Toast-Benachrichtigungen manipulieren das DOM, das während des serverseitigen Renderings nicht verfügbar ist. Wickeln Sie Ihren Toast-Container in eine ClientOnly-Komponente ein oder registrieren Sie Ihre Toast-Bibliothek als clientseitiges Nuxt-Plugin mit dem .client.ts-Datei-Suffix. Dies stellt sicher, dass die Toast-Logik nur im Browser ausgeführt wird.

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.

OpenReplay