Lógica (Domain)
Toast
import { ToastBody } from "./ToastBody";import { ToastPosition } from "./ToastPositions";export class Toast { id: number position: ToastPosition; body: ToastBody; duration: number; constructor(body: ToastBody, position: ToastPosition, duration?: number) { this.id = this.randomId() this.body = body; this.position = position; this.duration = duration ?? 2500; } private randomId() { return Math.floor(Math.random() * new Date().getMilliseconds()); }}ToastBody
type ToastProps = { title: string; color?: string; icon?: any; description: string;};export class ToastBody { title: string; description: string; icon: any; color: string = ""; constructor(props: ToastProps) { this.title = props.title; this.description = props.description; this.color = props.color ?? "green"; this.icon = props.icon ?? ""; }}ToastPosition
export type ToastPosition = "top" | "bottom";Casos de uso (Aplications)
useToast
import { Toast } from "../domain/Toast";import { ToastBody } from "../domain/ToastBody";import { ToastsOnReactiveMemory } from "../infraestructure/persistence";const toastOnReactiveMemory = new ToastsOnReactiveMemory();export function useToast() { const add = ( title: string, description: string, color?: string, icon?: string ) => { const toast = new Toast( new ToastBody({ title, description, color, icon, }), "top" ); toastOnReactiveMemory.add(toast); }; const remove = (toast: Toast) => { toastOnReactiveMemory.remove(toast); }; return { toasts: toastOnReactiveMemory.toasts, add, remove, };}Persistencia (Infraestructure)
Persistencia en memoria reactiva
import { ref, Ref } from "vue";import { Toast } from "../domain/Toast";export class ToastsOnReactiveMemory { private conatiner: Ref<Toast[]> = ref([]); add(toast: Toast) { this.toasts.value.push(toast); } remove(toast: Toast) { const index = this.toasts.value.findIndex((t) => t.id === toast.id); this.toasts.value.splice(index, 1); } get toasts() { return this.conatiner; }}Componentes
Los estilos quedan a tu imaginación
ToastContainer
La función principal de este componente es recorrer el contenedor de los toast y asignar sus propiedades.
<template> <div> <span v-for="t of toasts"> <Toast :toast="t" /> </span> </div></template><script lang="ts" setup>import { useToast } from './application/useToast'import Toast from './Toast.vue'const { toasts } = useToast()</script>Toast
La responsabilidad de este componente es solo obtener los atributos desde el ToastContainer y mostrarlos
<template> {{ toast.id }} {{ toast.body }}</template><script lang="ts" setup>import { onMounted } from 'vue';import { useToast } from './application/useToast';import { Toast } from './domain/Toast';const props = defineProps<{ toast: Toast}>()const { remove } = useToast()onMounted(() => { const time = setTimeout(() => { remove(props.toast) clearTimeout(time) }, props.toast.duration)})</script>