Vuex - La proprietà calcolata "nome" è stata assegnata ma non ha setter


108

Ho un componente con una convalida del modulo. È un modulo di pagamento in più passaggi. Il codice seguente è per il primo passaggio. Vorrei convalidare che l'utente abbia inserito del testo, memorizzare il proprio nome nello stato globale e quindi inviarlo al passaggio successivo. Sto usando vee-validate e vuex

<template>
<div>
    <div class='field'>
        <label class='label' for='name'>Name</label>
        <div class="control has-icons-right">

            <input name="name" v-model="name" v-validate="'required|alpha'" :class="{'input': true, 'is-danger': errors.has('name') }" type="text" placeholder="First and Last">
            <span class="icon is-small is-right" v-if="errors.has('name')">
                <i class="fa fa-warning"></i>
            </span>
        </div>
        <p class="help is-danger" v-show="errors.has('name')">{{ errors.first('name') }}</p>

    </div>
    <div class="field pull-right">
        <button class="button is-medium is-primary" type="submit" @click.prevent="nextStep">Next Step</button>
    </div>
</div>
</template>

<script>
export default {
    methods: {
        nextStep(){
            var self = this;

            // from baianat/vee-validate
            this.$validator.validateAll().then((result) => {
                if (result) {
                    this.$store.dispatch('addContactInfoForOrder', self);
                    this.$store.dispatch('goToNextStep');
                    return;
                }
            });
        }
    },
    computed: {
        name: function(){
            return this.$store.state.name;
        }
    }
}
</script>

Ho un negozio per la gestione dello stato dell'ordine e la registrazione del nome. In definitiva, vorrei inviare tutte le informazioni dal modulo in più passaggi al server.

export default {
  state: {
    name: '',
  },

  mutations: {
    UPDATE_ORDER_CONTACT(state, payload){
      state.name = payload.name;

    }
  },

  actions: {
    addContactInfoForOrder({commit}, payload) {
      commit('UPDATE_ORDER_CONTACT', payload);
    }
  }
}

Quando eseguo questo codice ottengo un errore that Computed property "name" was assigned to but it has no setter.

Come associo il valore dal campo del nome allo stato globale? Vorrei che fosse persistente in modo che anche se un utente torna indietro di un passaggio (dopo aver fatto clic su "Passaggio successivo") vedrà il nome che ha inserito in questo passaggio


1
Oltre alla risposta di Roy J, sembra che l'uso v-forsu un computer calcolato senza un setter lanci anche questo avvertimento.
jsiegal

Risposte:


192

Se stai andando a v-modelun computer, ha bisogno di un setter . Qualunque cosa tu voglia che faccia con il valore aggiornato (probabilmente scrivilo in $store, considerando che è quello da cui il tuo getter lo tira) lo fai nel setter.

Se la riscrittura nel negozio avviene tramite l'invio del modulo, non vuoi v-model, vuoi solo impostare :value.

Se desideri avere uno stato intermedio, in cui viene salvato da qualche parte ma non sovrascrive l'origine nell'invio del $storemodulo fino a quando non viene inviato, dovrai creare tale elemento di dati.


38
:valuefinita v-model. Grazie!
Connor Leech

4
Grazie ... ho corretto anche il mio [vue warn]. Avevo un cassetto di navigazione che richiedeva un valore vero / falso (di sola lettura) ma ci avevo messo un v-model.
GA

26

Dovrebbe essere così.

Nel tuo Component

computed: {
        ...mapGetters({
                nameFromStore: 'name'
            }),
        name: {
           get(){
             return this.nameFromStore
           },
           set(newName){
             return newName
           } 
        }
    }

Nel tuo negozio

export const store = new Vuex.Store({
         state:{
             name : "Stackoverflow"
         },
         getters: {
                 name: (state) => {
                     return state.name;
                 }
         }
}

1
Scusa per aver rianimato una tua vecchia risposta, ma perché usare un getter in questo caso? Perché non restituire this.nameFromStore da mapState? A quanto pare funziona altrettanto bene.
Jake

@Jake Per questo esempio, quello che stai dicendo è giusto. Ma quando vuoi manipolare i dati salvati nel negozio, puoi farlo all'interno di getter ma se usi this.nameFromStoredirettamente non puoi manipolare i dati.
OhhhThat Varun

1
Grazie per il chiarimento :)
Jake

@ Jake Nessun problema!
OhhhThat Varun

3

Per me stava cambiando.

this.name = response.data;

A quanto calcolato restituisce così;

this.$store.state.name = response.data;

0

Voglio solo menzionare il motivo per cui appare questo avviso, ogni volta che creiamo un valore calcolato è getter per impostazione predefinita, dobbiamo definire esplicitamente i setter per la proprietà calcolata,

come menzionato nella documentazione di VueJs, Computed Setter

la tua proprietà calcolata sarà simile a questa

   name: {
       get: function () {
          return yourName
       },
       set: function (newName) {
          return yourNewName
       }

Il modo più appropriato è utilizzare mapStateper ottenere il nome dal negozio e un'altra opzione che definisci getter nel tuo negozio e utilizzare mapGettersper estrarre il nome dal negozio,

Cosa importante da sapere: i getter in negozio vengono utilizzati quando si desidera ottenere dati calcolati dal negozio, quindi in quel momento si definisce la logica nei getter che ti forniscono dati calcolati

esempio di getter

getters = {
  isLoggedIn (state) {
    return !!state?.activeUser?.id
  }
}

questo getter controlla il tuo stato per l'utente attivo e restituisce true se loggato e false se non loggato,

in seguito nell'intera applicazione usiamo mapGettersper estrarre questa isLoggedInproprietà e aggiungere controlli in base a ciò

spero che qualcuno trovi questo aiuto completo :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.