使用 Vue、Vuetify 和 Vuex 创建一个全局小吃店

问题描述

我尝试创建一个全局小吃栏以在每次发生 axios http 错误时触发,我遵循了本教程:https://dev.to/stephannv/how-to-create-a-global-snackbar-using-nuxt-vuetify-and-vuex-1bda

但我不想使用 Nuxt,只想使用 Vue、Vuex 和 Vuetify,所以我尝试创建一个随处可用的插件,但出现以下错误[vuex] unkNown mutation type: snackbar/showMessageTypeError: Cannot read property '$snackbar' of undefined

这是我的代码

src/main.js

import Vue from 'vue'
import router from "@/router";
import "./filters/filters";

import App from './App.vue'

import vuetify from "@/plugins/vuetify";

import VueSignaturePad from 'vue-signature-pad';
import axios from "axios";

import store from "@/store/snackbar";
import snackbarPlugin from "@/plugins/snackbar";

Vue.prototype.$http = axios;

Vue.config.productionTip = false

Vue.use(snackbarPlugin,{ store });
Vue.use(VueSignaturePad);

axios.interceptors.response.use(
    function (response) {
        return response;
    },function (error) {
        // handle error
        if (error.response) {
            this.$snackbar.showMessage({ content: error.response.data,color: 'error',timeout: 10000 })
        }
    });

new Vue({
    router,store,vuetify,render: h => h(App)
}).$mount('#app')

src/store/snackbar.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        content: '',color: '',timeout: ''
    },mutations: {
        showMessage (state,payload) {
            state.content = payload.content
            state.color = payload.color
            state.timeout = payload.timeout
        }
    }
});

export default store;

src/plugins/snackbar.js

const snackbarPlugin = {
    install: (Vue,{store}) => {
        if (!store) {
            throw new Error('Please provide vuex store.');
        }

        Vue.prototype.$snackbar = {
            showMessage: function ({
                                       content = '',color = '',timeout = ''
                                   }) {
                store.commit(
                    'snackbar/showMessage',{content,color,timeout},{root: true}
                );
            }
        };
    },};

export default snackbarPlugin;

src/utils/Snackbar.vue

<template>
    <v-snackbar v-model="show" :color="color" elevation="20">
        {{ message }}
        <v-btn color="accent" @click.native="show = false">
            <v-icon>close</v-icon>
        </v-btn>
    </v-snackbar>
</template>

<script>
export default {
    data() {
        return {
            show: false,message: "",color: "",timeout: 5000
        };
    },created () {
        this.$store.subscribe((mutation,state) => {
            if (mutation.type === 'snackbar/showMessage') {
                this.message = state.snackbar.content
                this.color = state.snackbar.color
                this.timeout = state.snackbar.timeout
                this.show = true
            }
        })
    }
};
</script>

src/App.vue

<template>
    <v-app>
        <Snackbar></Snackbar>
        <side-bar/>
        <Header/>
        <Main/>
    </v-app>
</template>

<script>
    import Snackbar from "@/utils/Snackbar";
    import SideBar from "@/components/layouts/SideBar";
    import Header from "@/components/layouts/Header";
    import Main from "@/components/layouts/Main";

    export default {
        name: 'App',components: {
            Snackbar,SideBar,Header,Main
        },beforeMount() {
            console.log('app')
            this.getRole()
            this.getEtats()
        },methods: {
            getRole() {
                this.$http.get('/rol')
                    .then(response => {
                        let agent = {}
                        agent.role = response.data.data.role
                        agent.username = response.data.data.username
                        localStorage.setItem('badge.agent',JSON.stringify(agent))
                    })
                    .catch(function (error) {
                        console.log(error)
                    })
            },getEtats() {
                this.$http.get('/nyx/badge/demande/accesnro/etats')
                    .then(response => {
                        localStorage.setItem('badge.etats',JSON.stringify(response.data.data))
                    })
                    .catch(function (error) {
                        console.log(error)
                    })
            }
        }
    }
</script>

我故意在 /role 路由上抛出 404 错误显示小吃栏,但错误发生了。

请问您知道我在this.$snackbar.showMessage ({content: error.response.data,timeout: 10000 })调用 main.js 时出了什么问题吗?

解决方法

因为你没有使用 Vuex 模块 (https://vuex.vuejs.org/guide/modules.html),所以你应该调用没有小吃栏前缀的提交:

store.commit('showMessage',{
    content,color,timeout}
);

查看此帖子 (Using vuejs plugin on the main.js file)。有说明,如何同时在main.js和App中使用plugin。

main.js

import Vue from "vue";
import router from "@/router";
import "./filters/filters";

import App from "./App.vue";

import vuetify from "@/plugins/vuetify";

import VueSignaturePad from "vue-signature-pad";
import axios from "axios";

import store from "@/store/snackbar";
import snackbarPlugin from "@/plugins/snackbar";

Vue.prototype.$http = axios;

Vue.config.productionTip = false;

Vue.use(snackbarPlugin,{ store });
Vue.use(VueSignaturePad);

axios.interceptors.response.use(
  function(response) {
    return response;
  },function(error) {
    // handle error
    if (error.response) {
      snackbarPlugin.showMessage({
        content: error.response.data,color: "error",timeout: 10000
      });
    }
  }
);

new Vue({
  router,store,vuetify,render: h => h(App)
}).$mount("#app");

snackbar.js

import store from "../store/snackbar";

const snackbarPlugin = {
  showMessage: ({ content = "",color = "",timeout = "" }) => {
    store.commit("snackbar/showMessage",{ content,timeout },{ root: true });
  },install: (Vue,{ store }) => {
    if (!store) {
      throw new Error("Please provide vuex store.");
    }
    Vue.prototype.$snackbar = snackbarPlugin;
  }
};

export default snackbarPlugin;

main.js

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...