我尝试创建一个全局的零食栏来触发每次axios http错误发生,我遵循这个教程:https://dev.to/stephannv/how-to-create-a-global-snackbar-using-nuxt-vuetify-and-vuex-1bda
但是我不想使用next,只有Vue, Vuex和Vuetify,所以我试图创建一个插件,但我得到这些错误:[vuex] unknown mutation type: snackbar/showMessage
和TypeError: 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错误以打开零食栏,但错误发生了。
当我在main.js
中调用this.$snackbar.showMessage ({content: error.response.data, color: 'error', timeout: 10000 })
时,您知道有什么问题吗?
因为你不使用Vuex模块(https://vuex.vuejs.org/guide/modules.html),你应该调用commit不带snackbar前缀:
store.commit('showMessage',{
content, color, timeout}
);
检查这篇文章(在main.js文件上使用vuejs插件)。有一个解释,如何在main.js和App中同时使用插件。
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, color, timeout }, { root: true });
},
install: (Vue, { store }) => {
if (!store) {
throw new Error("Please provide vuex store.");
}
Vue.prototype.$snackbar = snackbarPlugin;
}
};
export default snackbarPlugin;
main.js