Vuex - Die berechnete Eigenschaft "Name" wurde zugewiesen, hat jedoch keinen Setter


108

Ich habe eine Komponente mit einer Formularvalidierung. Es ist ein mehrstufiges Checkout-Formular. Der folgende Code ist für den ersten Schritt. Ich möchte überprüfen, ob der Benutzer Text eingegeben hat, seinen Namen im globalen Status speichern und dann zum nächsten Schritt senden. Ich benutze vee-validate und 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>

Ich habe ein Geschäft für die Bearbeitung des Bestellstatus und die Aufzeichnung des Namens. Letztendlich möchte ich alle Informationen aus dem Mehrschrittformular an den Server senden.

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

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

    }
  },

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

Wenn ich diesen Code ausführe, wird eine Fehlermeldung angezeigt Computed property "name" was assigned to but it has no setter.

Wie binde ich den Wert aus dem Namensfeld an den globalen Status? Ich möchte, dass dies dauerhaft bleibt, damit ein Benutzer, selbst wenn er einen Schritt zurückgeht (nachdem er auf "Nächster Schritt" geklickt hat), den Namen sieht, den er in diesem Schritt eingegeben hat


1
Zusätzlich zu Roy Js Antwort scheint es, als würde die Verwendung v-forauf einem Computer ohne Setter auch diese Warnung auslösen.
Jsiegal

Antworten:


189

Wenn Sie zu v-modeleinem Computer gehen, benötigt er einen Setter . Was auch immer Sie möchten, dass es mit dem aktualisierten Wert zu tun hat (wahrscheinlich schreiben Sie es in den $store, wenn Sie bedenken, dass Ihr Getter es daraus zieht), tun Sie im Setter.

Wenn das Zurückschreiben in den Store über das Senden von Formularen erfolgt, möchten Sie dies nicht v-model, sondern nur festlegen :value.

Wenn Sie einen Zwischenzustand haben möchten, in dem er irgendwo gespeichert ist, aber die Quelle in der $storeBis-Formular- Übermittlung nicht überschreibt , müssen Sie ein solches Datenelement erstellen.


37
:valuevorbei v-model. Danke dir!
Connor Leech

4
Danke ... habe auch meine [vue warn] behoben. Ich hatte eine Navigationsschublade, die einen (schreibgeschützten) True / False-Wert erforderte, aber ich hatte ein V-Modell hinzugefügt.
GA

26

Es sollte so sein.

In Ihrer Komponente

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

In deinem Laden

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

1
Es tut mir leid, dass Sie eine alte Antwort wiederbelebt haben, aber warum in diesem Fall einen Getter verwenden? Warum nicht this.nameFromStore von mapState zurückgeben? Es funktioniert anscheinend genauso gut.
Jake

@Jake Für dieses Beispiel ist das, was Sie sagen, richtig. Wenn Sie jedoch die im Speicher gespeicherten Daten bearbeiten möchten, können Sie dies in getter tun. Wenn Sie jedoch this.nameFromStoredirekt verwenden, können Sie die Daten nicht bearbeiten.
OhhhThatVarun

1
Danke für die Klarstellung :)
Jake

@ Jake Kein Problem!
OhhhThatVarun

3

Für mich hat sich das geändert.

this.name = response.data;

Zu dem, was berechnet wird, kehrt so zurück;

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

0

Ich möchte nur erwähnen, warum diese Warnung angezeigt wird. Wenn wir einen berechneten Wert erstellen, der standardmäßig getter ist, müssen wir explizit Setter für berechnete Eigenschaften definieren.

wie in der Dokumentation von VueJs, Computed Setter erwähnt

Ihre berechnete Eigenschaft sieht folgendermaßen aus

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

Besser geeignet ist es, mapStateden Namen aus dem Geschäft abzurufen und mit einer anderen Option den Getter in Ihrem Geschäft zu definieren und mapGettersden Namen aus dem Geschäft zu extrahieren.

Wichtig zu wissen: Getter im Speicher werden verwendet, wenn Sie berechnete Daten aus dem Speicher abrufen möchten. Zu diesem Zeitpunkt definieren Sie Logik in Gettern, mit denen Sie berechnete Daten erhalten

Beispiel für Getter

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

Dieser Getter überprüft Ihren Status auf aktiven Benutzer und gibt true zurück, wenn er angemeldet ist, und false, wenn er nicht angemeldet ist.

Später in der gesamten Anwendung mapGettersextrahieren wir diese isLoggedInEigenschaft und fügen dementsprechend Prüfungen hinzu

hoffe jemand findet diese hilfe voll :)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.