Salut

j'ai un problème avec mon Vuex en mode strict qui m'affiche une alerte :

[Vue warn]: Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] Do not mutate vuex store state outside mutation handlers."

(found in <Root>)

Cette erreur s'affiche quand je change l'ordre des éléments (au moment du drop, seulement si l'ordre a changé).

J'ai essayé de simplifier au maximum (j'ai viré toutes les requêtes assynchrones etc.) et de reproduire le problème dans un JSFiddle mais l'erreur ne s'affiche pas (je ne sais pas si elle ne s'affiche pas ou si elle n'existe pas) : https://jsfiddle.net/bestiole/pmvwhwcq/4/

Du coup voici mon code, mais à part la fragmentation en fichiers, je crois qu'il n'y a pas de différence :

Tree.vue

<template>
    <div class="tree">
        <div v-for="(list, listName) in pages">
            <h3>List {{listName}}</h3>
            <draggable v-model="pages[listName]" :options="{group:{pull:true,put:true},animation: 150}" class="sortable-list">
                <div v-for="page in pages[listName]" :key="page.id" class="sortable">{{page.title}}</div>
            </draggable>
        </div>
    </div>
</template>

<script
    export default {
        name: 'tree',
        computed: {
            pages: {
                get() {
                    return this.$store.state.pages
                },
                set(value) {
                    this.$store.commit('setPages', value)
                }
            }
        }
    }
</script>

Store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
    strict: true,
    state: {
        pages: {'menu' : [
                {'id' : 0, 'title' : 'home'},
                {'id' : 1, 'title' : 'about'},
                {'id' : 2, 'title' : 'contact'}
            ],
            'specials' : [
                {'id' : 3, 'title' : 'special'},
                {'id' : 4, 'title' : 'weirdo'},
            ]
        }
    },
    mutations: {
        setPages: (state, pages) => {
            state.pages = pages
        }
    }
});

Je pense que le problème pourrait être dû à la boucle f-vor sur l'objet pages, et l'utilisation de pages[listName] comme v-model mais j'ai l'impression de gérer ça convenablement... (mais je débute sur Vuejs)

selon la doc Vue.Draggable est compatible avec Vuex, et les seuls problèmes liés au mode strict dans les issues sont des erreurs des utilisateurs...

Quelqu'un a une idée ?

1 réponse


wesh poussin
Auteur
Réponse acceptée

problème résolu : https://forum.vuejs.org/t/vuex-vue-draggable-vuex-do-not-mutate-vuex-store-state-outside/30802/5

Voici mon code final :

Structure.vue

<template>
    <div class="structure">
        <tree v-for="(value, key, index) in pages" :key="index" :name="key"></tree>
    </div>
</template>

<script>
    import tree from './Tree.vue'
    import axios from 'axios'

    export default {
        name: 'structure',
        components: {
            tree
        },
        computed: {
            pages: {
                get() {
                    return this.$store.state.pages
                },
                set(value) {
                    this.$store.commit('setPages', value)
                }
            }
        },
        created () {
            axios.get('/api/pages').then(response => {
                this.pages = response.data.pages
            })
        }
    }
</script>

Tree.vue

<template>
    <div>
        <h3>List {{name}}</h3>
        <draggable v-model="pagesGroup" :options="{group:{pull:true,put:true},animation: 150}" @end="handleDrop" class="sortable-list">
            <div v-for="page in pagesGroup" :key="page.id" class="sortable">{{page.title}}</div>
        </draggable>
    </div>
</template>

<script>
    export default {
        name: 'tree',
        props: [
            'name'
        ],
        computed: {
            pagesGroup: {
                get () {
                    return this.$store.state.pages[this.name]
                },
                set(value) {
                    this.$store.commit('setPagesGroup', {
                        value,
                        key: this.name,
                    })
                }
            }
        },
        methods: {
            handleDrop () {
                this.$store.dispatch('storePages')
            }
        },
        created () {
            console.log(this.pagesGroup);
        }
    }
</script>

store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
    strict: true,
    state: {
        pages: {}
    },
    mutations: {
        setPages (state, pages) {
            state.pages = pages
        },
        setPagesGroup (state, { value, key }) {
            state.pages[key] = value
        }
    },
    actions: {
        storePages (context) {
            let jsonPages = JSON.parse(JSON.stringify(context.state.pages))
            console.log(jsonPages)
        }
    }
});