本篇在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項目]陣列toasts和showToast函式。
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')
測試
在[新增訂單頁面]新增一筆訂單後,在右上角會彈出"新增訂單成功!"的提示訊息,此即為Toast。
接著實作刪除訂單。
沒有留言:
張貼留言