如何使用 primeVue toast 创建可重用的 toastService?

问题描述 投票:0回答:7
我想知道是否有一种方法可以通过 primevue toast 函数调用创建可重用的脚本/类/服务,这样我就不需要在每个组件中直接调用 primevue toast 函数。

到目前为止,我尝试做的是创建一个

ToastService.ts,如下所示:

import { useToast } from 'primevue/usetoast'; const toast = useToast(); export function addMsgSuccess(): void { toast.add({ severity: 'success', summary: 'Test', detail: 'Test', life: 3000 }); }
但是这段代码使我的应用程序崩溃,并且出现以下错误:

未捕获错误:useToast 未提供 PrimeVue Toast! (usetoast.esm.js?18cb:8:1) eval (ToastService.ts?73ba:3:1) 模块../src/shared/service/ToastService.ts (app.js:1864:1)

webpack_require (app.js:849:30) fn (app.js:151:20) eval (cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader /index.js?!./node_modules/eslint-loader/index.js?!./src/views/cadastro-plano/CadastroPlano.ts?vue&type=script&lang=ts:31:87) 模块../node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js?!./node_modules/eslint- loader/index.js?!./src/views/cadastro-plano/CadastroPlano.ts?

有谁知道如何解决这个问题,或者创建调用 add() 的函数,这样我就不需要每次都调用它?

typescript vue.js vuejs3 toast primevue
7个回答
11
投票
这个解决方案对我有用,但我不确定这是一个好的解决方案。

首先:从 main.ts 导出应用程序

// main.ts import {createApp} from 'vue'; import App from '@/App.vue'; import PrimeVue from 'primevue/config'; import ToastService from 'primevue/toastservice'; export const app = createApp(App); app.use(PrimeVue); app.use(ToastService); app.mount('#app')
第二:导入应用程序并使用 toast 服务 

app.config.globalProperties


// myToastService.ts import {ToastSeverity} from 'primevue/api'; import {app} from '@/main'; const lifeTime = 3000; export function info(title: string = 'I am title', body: string = 'I am body'): void { app.config.globalProperties.$toast.add({severity: ToastSeverity.INFO, summary: title, detail: body, life: lifeTime}); }; export function error(title: string = 'I am title', body: string = 'I am body'): void { app.config.globalProperties.$toast.add({severity: ToastSeverity.ERROR, summary: title, detail: body, life: lifeTime}); };
第三:在组件中导入 myToastService。

// myTestToastComponent.vue <script setup lang="ts"> import {info, error} from '@/components/myToastService'; info(); </script>
    

7
投票
也许以下解决方案适合您:

在 App.vue 中添加 Toast 并添加检查商店消息的手表

<template> <router-view /> <Toast position="bottom-right" group="br" /> </template> <script> import { watch } from "vue"; import { useStore } from "vuex"; import { useToast } from "primevue/usetoast"; export default { setup() { const store = useStore(); const toast = useToast(); watch( () => store.getters.getErrorMessage, (message, prevMessage) => { console.log("error message", message); if (message) { toast.add({ severity: "error", summary: "Error", detail: message, group: "br", life: 6000, }); } } ); }, }; </script>
商店

import { createStore } from "vuex"; export default createStore({ state: { errorMessage: "" }, mutations: { setErrorMessage(state, payload) { state.errorMessage = payload; }, }, actions: {}, modules: {}, getters: { getErrorMessage: (state) => state.errorMessage, }, });
然后,在任何其他组件中只需更新消息

store.commit("setErrorMessage", error.message);
    

2
投票
玩了一段时间后,我找到了一个我认为很优雅的解决方案,尽管它使用了 Pinia。使用这种方法,您也可以在辅助函数中调用 toast,并且重用这些函数非常简单。

main.ts

import { createApp } from "vue"; import App from "./App.vue"; import { createPinia } from "pinia"; import PrimeVue from "primevue/config"; import ToastService from "primevue/toastservice"; import Toast from "primevue/toast"; createApp(App) .use(router) .use(PrimeVue) .use(createPinia()) .use(ToastService) .component("Toast", Toast) .mount("#app");

接口.ts

export interface Message { severity: string; summary: string; detail: string; }

useNotifications.ts

import { defineStore } from "pinia"; import { Message } from "@interfaces"; interface State { info: Message; notify: Message; confirm: Message; } const useNotifications = defineStore({ id: "notificationStore", // Might be better to only have one piece of state, but this is the solution I went with // info for basic notifs, notify for sticky notifs, confirm for notifs that need confirmation state: (): State => ({ info: { severity: "", summary: "", detail: "", }, notify: { severity: "", summary: "", detail: "", }, confirm: { severity: "", summary: "", detail: "", }, }), }); export default useNotifications;

应用程序.vue

<script setup lang="ts"> import { useToast } from "primevue/usetoast"; import { useNotifications } from "@store"; import { Message } from "@interfaces"; const notificationStore = useNotifications(); const toast = useToast(); // Watches changes on notificationStore throughout the app notificationStore.$subscribe((mutation, state) => { // Checks which part of the state has been mutated, and updates that state based on those conditions // mutation.events.key will throw a TypeScript error, but it will still work (until build time where another solution should be found) const key = mutation.events.key; if (key === "info") { const { severity, summary, detail } = state.info; toast.add({ severity, summary, detail, life: 3000, group: "br" }); } else if (key === "notify") { const { severity, summary, detail } = state.notify; toast.add({ severity, summary, detail, group: "br" }); } else if (key === "confirm") { const { severity, summary, detail } = state.confirm; toast.add({ severity, summary, detail, group: "bc" }); } }); // Use provide to make Toast functionality easily injectable provide("toastConfirm", (args: Message) => { const { severity, summary, detail } = args; notificationStore.confirm = { severity, summary, detail }; }); provide("toastNotify", (args: Message) => { const { severity, summary, detail } = args; notificationStore.notify = { severity, summary, detail }; }); provide("toastInfo", (args: Message) => { const { severity, summary, detail } = args; notificationStore.info = { severity, summary, detail }; }); const denyToast = () => { toast.removeGroup("bc"); }; // Have not figured out how to make this function useable const acceptToast = () => { toast.removeGroup("bc"); }; </script> <template> <!-- This group will represent the toasts I do not wish to have to confirm --> <Toast position="bottom-right" group="br" /> <!-- The 'confirmable' toast template is basically copy pasted from PrimeVue docs --> <!-- This Toast will appear in the bottom center --> <Toast position="bottom-center" group="bc"> <template #message="slotProps"> <div> <div> <i class="pi pi-exclamation-triangle" /> <h4>{{ slotProps.message.summary }}</h4> <p>{{ slotProps.message.detail }}</p> </div> <div> <div> <Button class="p-button-danger" label="No" @click="denyToast" /> <Button class="p-button-success" label="Yes" @click="acceptToast" /> </div> </div> </div> </template> </Toast> </template>

AnyChildComponent.vue

<script setup lang="ts"> import { inject } from "vue"; import { Message } from "@interface"; const notifyMe = inject("toastNotify", (args: Message) => {}); const handleClick = () => { notifyMe({ severity: "success", summary: "success!", detail: "this is from child component", }); }; </script> <template> <Button @click="handleClick" /> </template>

HelperFunction.ts 的用法示例

import { useNotifications } from "@store"; // Database helper function const send = async (channel: string, data?: Object) => { const notificationStore = useNotifications(); if (data) data = JSON.parse(JSON.stringify(data)); // response will return something like: { message: "Query failed", error: error } or { message: "Query succeeded", success?: returnData } const response = await window.electron.ipcRenderer.invoke(channel, data); if (response.error) { console.log(response.error); notificationStore.notify = { severity: "danger", summary: "Error", detail: response.message, }; } else { notificationStore.info = { severity: "success", summary: "Success", detail: response.message, }; if (response.success) return response.success; } }; export default send;
    

2
投票
另一种选择是在单个位置处理 toast (

App.vue

),然后通过消息总线接收它们。

先在

main.js

设立巴士:

import mitt from 'mitt' const toastBus = mitt() const app = createApp(App) // Provide the bus for injection for use by components app.provide('toastBus', toastBus) // Export the bus for use by 'non-component' scripts export { toastBus }
然后将总线注入到App.vue中,监听事件并生成toast:

<template> <div id="app"></div> <Toast /> </template> <script> import { inject } from 'vue' import { useToast } from 'primevue/usetoast' const toastBus = inject('toastBus') const toast = useToast() toastBus.on('*', (type, args) => { if (type === 'add') { toast.add(args) } else if (type === 'remove') { toast.remove(args) } })
然后从组件发送 toast:

let toastBus = inject('toastBus') toastBus.emit('add', { severity: 'success', summary: 'Test', detail: 'Test', life: 3000 })
或者来自非组件代码:

import { toastBus } from './main' toastBus.emit('add', { severity: 'success', summary: 'Test', detail: 'Test', life: 3000 })
    

1
投票
答案:

上面@match,对于那些正在苦苦挣扎的人,将 App.vue 更改为:

<template> <div id="app"></div> <Toast /> </template> <script> import { inject } from 'vue' import { useToast } from 'primevue/usetoast' export default { setup() { const toastBus = inject('toastBus') const toast = useToast() toastBus.on('*', (type, args) => { if (type === 'add') { toast.add(args) } else if (type === 'remove') { toast.remove(args) } }) } } </script>
    

1
投票

任何需要在 js 文件中使用 toast 的人的示例

// App.vue <template> <Toast /> </template> <script> import Toast from "primevue/toast"; export default { components: { Toast: Toast, }, </script>

// store.js import { useToast } from "primevue/usetoast"; export const StoreExample = defineStore("StoreExample", () => { const toast = useToast(); const onActionGetProducts = async () => { return API_EXAMPLE.onApiGetProducts().then(() => { toast.add({ severity: "success", summary: "Success Message", detail: "Order submitted", life: 3000, }); }); }; return { onActionGetProducts, }; });
    

0
投票
无需额外依赖或导入/导出应用程序的解决方案

它是更多的导入,但这样您就可以拥有合理的一致默认值。就我而言,从 main.js 导出任何内容都不是一个选项,因此如果没有额外的依赖项,这是我唯一的选择。

上课

在 toastNotificationHelper.js 中:

import {ToastSeverity} from 'primevue/api'; export class toastService { constructor(toastInstanse, defaultLifeTime) { this.toastInstanse = toastInstanse this.defaultLifeTime = defaultLifeTime ? defaultLifeTime : "3000" } displayInfo(title = 'Info', body = '', lifeTime = this.defaultLifeTime){ this.toastInstanse.add({severity: ToastSeverity.INFO, summary: title, detail: body, life: lifeTime}); } }
在您的组件中:

import { useToast } from 'primevue/usetoast'; import { toastService } from "@/utilities/toastNotificationHelper.js"; const toastNotifications = new toastService(useToast()) onMounted(() => { toastNotifications.displayInfo() });

有功能

在 toastNotificationHelper.js 中:

import {ToastSeverity} from 'primevue/api'; const defaultLifeTime = 3000; export function toastInfoNotification(toastInstanse, title = 'Info', body = '', lifeTime = defaultLifeTime) { toastInstanse.add({severity: ToastSeverity.INFO, summary: title, detail: body, life: lifeTime}); };
在您的组件中:

import { toastInfoNotification } from "@/utilities/toastNotificationService.js"; import { useToast } from 'primevue/usetoast'; const toast = useToast(); onMounted(() => { toastInfoNotification(toast) });
    
© www.soinside.com 2019 - 2024. All rights reserved.