【Vue.js】複数のトースト通知をグローバルイベントで制御する

【Vue.js】複数のトースト通知をグローバルイベントで制御する Vue.js

シンプルなトースト通知は便利ですが、実務では「複数の通知を同時に表示したい」「どこからでも呼び出したい」といったニーズも多くなります。本記事では、Vue 3で複数トーストの同時表示グローバルイベントによる通知呼び出しを可能にする拡張実装を紹介します。

構成の概要

  • ToastContainer.vue: トーストをまとめて管理・表示するコンポーネント
  • useToast(): 任意の場所からトーストを呼び出せるComposable
  • emit + on: グローバルイベントを使って通知を表示

ToastContainer.vue

トーストのリストを状態で管理し、追加・削除を制御するコンポーネントです。

<template>
  <div class="toast-container">
    <div
      v-for="toast in toasts"
      :key="toast.id"
      class="toast"
    >
      {{ toast.message }}
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const toasts = ref([]);

const addToast = (message) => {
  const id = Date.now();
  toasts.value.push({ id, message });

  setTimeout(() => {
    toasts.value = toasts.value.filter(t => t.id !== id);
  }, 3000);
};

// イベント登録
const handleEvent = (event) => {
  if (event.detail && event.detail.message) {
    addToast(event.detail.message);
  }
};

onMounted(() => {
  window.addEventListener('toast', handleEvent);
});
onUnmounted(() => {
  window.removeEventListener('toast', handleEvent);
});
</script>

<style scoped>
.toast-container {
  position: fixed;
  top: 20px;
  right: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 9999;
}
.toast {
  background: #333;
  color: #fff;
  padding: 0.8rem 1.2rem;
  border-radius: 5px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
</style>

トーストを呼び出すComposable(useToast.js)

Vueのどこからでもトースト通知を発行できる関数です。


// composables/useToast.js
export function useToast() {
  const showToast = (message) => {
    const event = new CustomEvent('toast', {
      detail: { message }
    });
    window.dispatchEvent(event);
  };

  return { showToast };
}

使い方例

どのコンポーネントからでも以下のように使えます。

<template>
  <button @click="notify">トースト通知を表示</button>
</template>

<script setup>
import { useToast } from '@/composables/useToast';

const { showToast } = useToast();

const notify = () => {
  showToast('操作が完了しました!');
};
</script>

App.vueにToastContainerを常時設置

トーストは全ページで使えるよう、App.vueに一度だけ設置しておきます。

<template>
  <router-view />
  <ToastContainer />
</template>

<script setup>
import ToastContainer from '@/components/ToastContainer.vue';
</script>

まとめ

この拡張構成により、Vueアプリのどこからでも複数のトースト通知を簡単に呼び出せるようになります。通知の見た目や位置、表示時間などはカスタマイズ可能で、ユーザー体験を向上させる重要な要素となります。

小規模なプロジェクトではこの構成で十分に実用的ですが、さらに高度な管理が必要な場合はPiniaVueUseなどの状態管理ライブラリと連携することも検討できます。