VueJS - VueX和flash消息

时间:2018-05-07 13:15:42

标签: vue.js vuex nuxt.js

我使用 VueJS 2 VueX NuxtJS Vue-Snotify artemsky/vue-snotify)用于闪光通知。

可能无法正确使用VueX,但我想发送在try / catch中捕获的错误。

try {
    throw new Error('test')
} catch (error) {
    this.$store.dispatch('errorHandler', error)
}

然后发送,如果有多个错误,VueX应该使用循环显示带有Snotify-View的通知。

actions: {
    async errorHandler (error) {
        this.$snotify.error(error)
        // and if multiple errors, then while on error
    }
}

您如何看待以及如何在VueX中恢复$ snotify的实例?

1 个答案:

答案 0 :(得分:3)

我意识到 app 实例是在 Vue 商店的初始化中注入的。因此,您可以通过this.app.$snotify访问所需的 Snotify 服务。

另外,商店中另一个接收 Nuxt 上下文作为第二个参数的地方是nuxtServerInit [2] 。因此,您可以使用下一个片段之类的东西访问服务

actions: {
    nuxtServerInit ({ state }, { app }) {
        // Workaround
        state.Snotify = app.$snotify // inject the context in the store
    },
    // Then, you can called as you want
    // There is not necessity to prefix the method with async keyword
    errorHandler ({ state }, message) {
        state.Snotify.error(message)
    }
}

在我看来,商店没有任何责任来处理数据的表示行为。因此,在这种情况下,商店的唯一目标是在要显示的组件之间传递消息,以即时消息的形式通过 Snotify < / strong>。因此,总结一下我对声明的赞赏,我认为行动仅是将商店状态更改为唯一事实来源的责任,由definition

您必须改用变异并仅存储 Object 。然后,在您的视图或 HOC (高阶组件)中,使用 Snotify (如果可用)设置演示逻辑。为了支持我的回答,我强烈建议this ,因为它具有更好的 API Vuex 进行通信,并且具有良好的演示界面(UI / UX)。免责声明:我并不是说这比 Snotify 更好,每一个都旨在满足至少在UX概念方面稍有不同的目的。两者都很棒,可以用任何一种方式来说明此用例。


我将为您更改第二个片段:

state: {
    flash: null
}
mutations: {
    // Just extract message from the context that you are set before
    SET_ERROR (state, { message, title = 'Something happens!' }) {
        state.flash = { 
            type: 'error',
            title, 
            message
        }
    },
    FLUSH_FLASH (state) {
        state.flash = null
    }
}

而且,我将其添加到某些view / layout / component / HOC中(我将 SFC 用作其最常用的方式)

<template>
    <vue-snotify />
    ...
</template>

<script>
   export default {
       // I use fetch because this is the lifecycle hook that executes 
       // immediately before page render is sure. And its purpose is to fill
       // the store before page render. But, to the best of my knowledge, 
       // this is the only place that you could use to trigger an immediately
       // executed function at the beginning of page render. However, also
       // you could use a middleware instead or "preferably use a wrapper 
       // component and get leverage of component lifecycle and use `mounted`" [4]
       fetch({ app, store }) {
           if (store.state.flash) {
               const { type, title, message: body } = store.state.flash
               const toast = app.$snotify[type](body, title)

               toast.on('destroyed', (t) => { store.commit('FLUSH_FLASH') })
           }
       },
       data: () => ({
           ...
       })
</script>

也许,上面的代码对您来说并不完整,但是我建议您应该测试一种类似的方法并满足您的需求。

编辑

我想根据我最近一次与组件生命周期相关的更新,为我的答案指出另一个改进。一开始,我实际上想将消息放入组件mounted方法中,但是后来我认为 Nuxt 页面的生命周期不同,直到看到{ {3}},并且意识到 Nuxt 在背景上仍然是 Vue 。因此,example实际上,任何页面也是组件。然后,您也可以执行很多语义方法。

<template>
    <vue-snotify />
    ...
</template>

<script>
   export default {
       data: () => ({
           ...
       }),
       // Show the flash at the beginning when it's necessary
       mounted: {
           if (this.notification) {
               const { type, title, message: body } = this.notification
               const toast = this.$snotify[type](body, title)

               toast.on('destroyed', (t) => { this.$store.commit('FLUSH_FLASH') })
           }
       },
       computed: {
           notification () {
               return this.$store.state.flush
           }
       }
</script>

参考文献

[1] definition

[2] https://zendev.com/2018/06/07/async-data-options-in-vue-nuxt.html

[3] https://twitter.com/krutiepatel/status/1000022559184764930

[4] https://github.com/artemsky/vue-snotify/blob/master/example/src/App/app.ts