Ошибка при вызове мутации vuex из компонента vue
Есть глобальной store, в котором state = текущее состояние, мутация CHANGE_CURRENT_MENU меняет текущее состояние.
Есть компонент NavMenu, в котором вызываю мутацию CHANGE_CURRENT_MENU и передаю в качестве параметра строку (название элемента, по которому произошел клик) => получаю ошибку: this.CHANGE_CURRENT_MENU is not a function
В чем проблема?
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
currentNav: 'interior',
showMenu: false
},
getters: {
NAV_LINKS: (state) => {
let links = {
interior: [
{
url: './assets/img/gallery/1.jpg',
name: 'interior',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
{
url: './assets/img/gallery/2.jpg',
name: 'interior',
route: {name: 'Gallery', params: {}},
active: ['Company']
}
],
exterior: [
{
url: './assets/img/gallery/3.jpg',
name: 'exterior',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
{
url: './assets/img/gallery/4.jpg',
name: 'exterior',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
{
url: './assets/img/gallery/5.jpg',
name: 'exterior',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
],
vr: [
{
url: './assets/img/gallery/6.jpg',
name: 'vr',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
{
url: './assets/img/gallery/7.jpg',
name: 'vr',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
{
url: './assets/img/gallery/8.jpg',
name: 'vr',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
],
animation: [
{
url: './assets/img/gallery/9.jpg',
name: 'animation',
route: {name: 'Gallery', params: {}},
active: ['Company']
},
{
url: './assets/img/gallery/10.jpg',
name: 'animation',
route: {name: 'Gallery', params: {
}},
active: ['Company']
},
{
url: './assets/img/gallery/11.jpg',
name: 'animation',
route: {name: 'Gallery', params: {
}},
active: ['Company']
},
],
}
if (state.currentNav === 'interior')
return links.interior
else return links.exterior
}
},
mutations: {
CHANGE_CURRENT_MENU(state, value) {
state.currentNav = value
}
}
})
Компонент:
<template>
<div class="nav-menu">
<ul class="accordion" v-for="(work, index) of works"
:key="`${work}_${index}`"
>
<li @click="openSubmenu(index)">
<div class="accordion__title"
>{{work.name}}</div>
<ul :class="['accordion__submenu submenu', {'hidden' : index !== activeIndex}]">
<li
class="submenu submenu__item"
v-for="category in work.categories"
:key="`${category}_${category}`"
@click="getCategoriesItem(category)"
>{{category}}
</li>
</ul>
</li>
</ul>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex';
export default {
name: 'NavMenu',
data: () => ({
activeIndex: null,
category: '',
works: [
{name: 'archetecture', categories: ['interior', 'exterior', 'vr', 'animation']},
{name: 'not archetecture', categories: ['commrcial', 'video', '3D art']}
]
}),
computed: {
...mapGetters(['NAV_LINKS']),
...mapMutations(['CHANGE_CURRENT_MENU'])
},
methods: {
openSubmenu(id) {
this.activeIndex = this.activeIndex === id ? null : id
},
getCategoriesItem(navItem) {
this.CHANGE_CURRENT_MENU(navItem)
},
}
}
</script>
Ответы (1 шт):
Автор решения: Николай Парахневич
→ Ссылка
Мутации можно вызывать из кода компонентов, используя this.$store.commit('xxx'), или применяя вспомогательный метод mapMutations, который проксирует вызовы store.commit через методы компонентов (для этого требуется наличие корневой ссылки на хранилище $store):
Рабочий пример:
const {
mapGetters,
mapMutations
} = Vuex;
const store = new Vuex.Store({
state: {
currentNav: 'interior',
showMenu: false
},
getters: {
NAV_LINKS: (state) => {
let links = {
interior: [{
url: './assets/img/gallery/1.jpg',
name: 'interior',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
{
url: './assets/img/gallery/2.jpg',
name: 'interior',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
}
],
exterior: [{
url: './assets/img/gallery/3.jpg',
name: 'exterior',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
{
url: './assets/img/gallery/4.jpg',
name: 'exterior',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
{
url: './assets/img/gallery/5.jpg',
name: 'exterior',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
],
vr: [{
url: './assets/img/gallery/6.jpg',
name: 'vr',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
{
url: './assets/img/gallery/7.jpg',
name: 'vr',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
{
url: './assets/img/gallery/8.jpg',
name: 'vr',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
],
animation: [{
url: './assets/img/gallery/9.jpg',
name: 'animation',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
{
url: './assets/img/gallery/10.jpg',
name: 'animation',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
{
url: './assets/img/gallery/11.jpg',
name: 'animation',
route: {
name: 'Gallery',
params: {}
},
active: ['Company']
},
],
}
if (state.currentNav === 'interior')
return links.interior
else return links.exterior
}
},
mutations: {
CHANGE_CURRENT_MENU(state, value) {
console.clear()
console.log('CHANGE_CURRENT_MENU', value)
state.currentNav = value
}
}
})
new Vue({
el: '#app',
store,
data: () => ({
activeIndex: null,
category: '',
works: [{
name: 'archetecture',
categories: ['interior', 'exterior', 'vr', 'animation']
},
{
name: 'not archetecture',
categories: ['commrcial', 'video', '3D art']
}
]
}),
computed: {
...mapGetters(['NAV_LINKS'])
},
methods: {
openSubmenu(id) {
this.activeIndex = this.activeIndex === id ? null : id
},
getCategoriesItem(navItem) {
this.CHANGE_CURRENT_MENU(navItem)
},
...mapMutations(['CHANGE_CURRENT_MENU']),
}
})
.hidden {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vuex.js"></script>
<div id="app">
<div class="nav-menu">
<ul class="accordion" v-for="(work, index) of works" :key="`${work}_${index}`">
<li>
<div @click.stop="openSubmenu(index)" class="accordion__title">{{work.name}}</div>
<ul :class="['accordion__submenu submenu', {'hidden' : index !== activeIndex}]">
<li class="submenu submenu__item" v-for="category in work.categories" :key="`${category}_${category}`" @click="getCategoriesItem(category)">{{category}}
</li>
</ul>
</li>
</ul>
</div>
</div>