不好
我意识到 app 实例是在 Vue 存储的初始化中注入的。因此,您可以通过this.app.$snotify 访问您想要的Snotify 服务。
此外,store 中另一个接收 Nuxt 上下文作为第二个参数 的地方是nuxtServerInit[2]。因此,您可以使用类似下一个 sn-p 的方式访问 服务。
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)
}
}
好
在我看来,store 没有任何责任来处理数据的呈现行为。因此,在这种情况下,store 的唯一目标是将要在其他组件中显示的消息传递为 flash message,并使用 Snotify 在这种特殊情况下。因此,总结一下我对声明的欣赏,我认为行动只负责将 商店 的 状态 更改为 唯一的事实来源 ,definition。
您必须改为使用 mutation 并仅存储 Object。然后,在您的视图中或 HOC(高阶组件)使用 Snotify 在可用的地方设置表示逻辑。为了支持我的回答,我强烈推荐 this library,因为它有更好的 API 可以与 Vuex 进行通信,而且它的演示效果也很好界面(UI/UX)。免责声明:我并不是说这个比 Snotify 更好,每个都是为了满足稍微不同的目的,至少就用户体验概念而言。两者都很棒,可以用任何一种方式来说明这个用例。
我会将您的第二个 sn-p 更改为:
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
}
}
另外,我将把它添加到一些视图/布局/组件/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 页面有一个 不同 生命周期,直到我看到这个 example并意识到 Nuxt 仍然是 Vue 在后台。因此,任何页面实际上也是definition 的组件。然后你也可以做一个语义化的方法。
<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]https://zendev.com/2018/06/07/async-data-options-in-vue-nuxt.html
[2]https://twitter.com/krutiepatel/status/1000022559184764930
[3]https://github.com/artemsky/vue-snotify/blob/master/example/src/App/app.ts
[4]https://medium.com/@fishpercolator/implementing-a-global-snackbar-in-nuxt-js-vuetify-using-vuex-a92b78e5651b