AdSense

網頁

2026/1/25

Vue Nuxt 3 Toast通知

本篇在Vue Nuxt 3專案實作Toast通知效果。


Toast(吐司)通知就是通常在網頁上方或右上角會跳出的訊息通知,不會讓頁面其他地方被鎖住或暫停。稱作Toast的原因是古早是從畫面右下方向上彈出,很像從烤土司機中彈出的吐司。

目前專案中的通知都是用alert,例如登入驗證錯誤、欄位未填寫和新增成功等,但alert除了比較陽春外,也會讓使用者有被打斷的感覺;然而有些通知例如[新增成功]比較適合不打斷使用者體驗的提示效果,所以接著把"新增訂單成功"的訊息改用Toast來顯示。


事前要求

參考「Vue Nuxt 3 新增訂單資料(表單 + POST API)」完成[新增訂單]頁面與功能。


新增資料型別

新增types/toast.ts,建立ToastType[Toast類型]和ToastItem[Toast項目]型別。ToastType有成功(success)和錯誤(error)兩種,用來標示Toast為成功或錯誤訊息來顯示對應的背景顏色。

types/toast.ts

export type ToastType = 'success' | 'error'

export type ToastItem = {
  id: number;
  message: string;
  type: ToastType;
};


建立組合函式

新增composables/useToast.ts,建立組合函式useToast,定義ref [Toast項目]陣列,最後回傳[Toast項目]陣列toastsshowToast函式。

showToast函式中把傳入的訊息資料放入[Toast項目]陣列(由於是ref所以資料變化時會渲染在畫面),5秒後從陣列中移除,代表訊息的保留時間。

composables/useToast.ts

import type { ToastType, ToastItem } from "~/types/toast"

const toasts = ref<ToastItem[]>([])
let id = 0

export function useToast() {
  
  function showToast(message: string, type: ToastType = 'success') {
    const toastId = id++
    toasts.value.push({ id: toastId, message, type })

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

  return {
    toasts,
    showToast,
  }
}


建立Toast元件

建立[Toast項目]元件components/Toast.vue,接收[訊息]message和[類型]type參數。

components/Toast.vue

<template>
  <div class="toast" :class="type">
    {{ message }}
  </div>
</template>

<script setup lang="ts">
defineProps<{
  message: string
  type?: 'success' | 'error'
}>()
</script>

<style scoped>
.toast {
  padding: 12px 16px;
  border-radius: 4px;
  color: white;
  font-size: 14px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  margin-bottom: 8px;
}

.toast.success {
  background-color: #16a34a;
}

.toast.error {
  background-color: #dc2626;
}
</style>


建立ToastContainer元件

建立[Toast容器]元件components/ToastContainer.vue,用來包裝及顯示每個[Toast項目],並用CSS固定在畫面最上層和右上角。

components/ToastContainer.vue

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

<script setup lang="ts">
import Toast from './Toast.vue'
import { useToast } from '~/composables/useToast'

const { toasts } = useToast()
</script>

<style scoped>
.toast-container {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 9999;
}
</style>


加入Toast元件

Nuxt專案的根元件app.vue為最外層元件,在所有頁面與layout之上,適合放置全站共用的元件,例如Toast通知、全域Modal或loading狀態,所以把<ToastContainer>放在app.vue

app.vue

<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
      <ToastContainer />
    </NuxtLayout>
  </div>
</template>


使用

修改pages/home/export/create.vue,把'新增訂單成功'原本的alert改為toast.showToast('新增訂單成功!', 'success')

pages/home/export/create.vue

import { useToast } from '~/composables/useToast'

const toast = useToast()
toast.showToast('新增訂單成功!', 'success')

github



測試

在[新增訂單頁面]新增一筆訂單後,在右上角會彈出"新增訂單成功!"的提示訊息,此即為Toast。



接著實作刪除訂單

沒有留言:

AdSense