web-dev-qa-db-fra.com

Setter pour la propriété calculée obtenue à partir du magasin dans vue.js

Je voudrais faire deux cases à cocher qui tirent de la valeur de store.js et les envoyer au backend via un formulaire:

<label>Notify me 
    <input type="checkbox" v-model="notification" value="notification" />       
</label>

<label>Email me 
    <input type="checkbox" v-model="email" value="email" />     
</label>

J'obtiens les valeurs comme une propriété calculée:

computed: {
  BASE_URL () {
    return this.$store.state.BASE_URL;  
  }, 
  notification () {
    return this.$store.state.notification; 
  },

  email () {
    return this.$store.state.email; 
  }
}

Le problème est que la vérification des cases à cocher ne modifie pas les valeurs dans le magasin, et en plus de cela, j'obtiens cet avertissement dans la console, comme:

vue.esm.js?65d7:479 [Vue warn]: Computed property "notification" was assigned to but it has no setter.

Je sais que l'on peut définir setter dans la propriété calculée, comme décrit dans les documents vue.js, mais je ne sais pas comment faire cela quand il y a plusieurs valeurs à définir, comme dans mon cas particulier .

Alors appréciez votre aide pour résoudre ce problème.

8
Karlom

Pour changer l'état de Vuex, vous aurez besoin d'une mutation.

À condition d'avoir une mutation setNotification pour changer l'état notification, vous pouvez configurer la propriété dans votre composant comme ceci:

computed: {
    notification: {
        get() { return this.$store.state.notification; },
        set(value) { this.$store.commit('setNotification', value); },
    },
},

Vous pouvez maintenant vous y connecter avec v-model="notification" comme d'habitude.

Voir Gestion des formulaires dans la documentation pour plus d'informations.


Puisque c'est une chose fréquente que je fais dans mes projets, j'ai écrit une fonction d'aide qui génère les propriétés calculées:

function mapStateTwoWay(...args) {
    const result = {};

    if (args.length === 1) {
        for (const prop of Object.keys(args[0])) {
            result[prop] = {
                get() { return this.$store.state[prop]; },
                set(value) { this.$store.commit(args[0][prop], value); },
            };
        }
    } else {
        for (const prop of Object.keys(args[1])) {
            result[prop] = {
                get() { return this.$store.state[args[0]][prop]; },
                set(value) { this.$store.commit(args[0] + '/' + args[1][prop], value); },
            };
        }
    }

    return result;
}

Utilisez-le comme ceci:

computed: {
    ...mapStateTwoWay({
        notifications: 'setNotifications',
        email: 'setEmail',
    }),

    // Namespaced
    ...mapStateTwoWay('namespace', {
        notifications: 'setNotifications',
        email: 'setEmail',
    }),
}
17
Decade Moon