Vuex - Obliczona właściwość „nazwa” została przypisana, ale nie ma metody ustawiającej

108

Mam komponent z jakąś walidacją formularza. Jest to wieloetapowa forma płatności. Poniższy kod dotyczy pierwszego kroku. Chciałbym sprawdzić, czy użytkownik wprowadził jakiś tekst, zapisać jego nazwę w stanie globalnym, a następnie wysłać do następnego kroku. Używam vee-validate i 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>

Mam sklep do obsługi stanu zamówienia i zapisywania nazwy. Docelowo chciałbym wysłać wszystkie informacje z wieloetapowego formularza na serwer.

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

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

    }
  },

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

Kiedy uruchamiam ten kod, pojawia się błąd Computed property "name" was assigned to but it has no setter.

Jak powiązać wartość z pola nazwy ze stanem globalnym? Chciałbym, aby to było trwałe, aby nawet jeśli użytkownik cofnął się o krok (po kliknięciu „Następny krok”), zobaczył nazwę wprowadzoną w tym kroku

Connor Leech
źródło
1
Oprócz odpowiedzi Roya J, wydaje się, że użycie v-forna komputerze obliczonym bez setera również powoduje to ostrzeżenie.
jsiegal,

Odpowiedzi:

192

Jeśli idziesz do v-modelkomputera, potrzebuje setera . Cokolwiek chcesz, żeby zrobiła ze zaktualizowaną wartością (prawdopodobnie zapisz ją do $store, biorąc pod uwagę to, z czego pobiera ją twój getter), robisz w ustawiającym.

Jeśli zapisanie go z powrotem do sklepu odbywa się poprzez przesłanie formularza, nie chcesz v-model, po prostu chcesz ustawić :value.

Jeśli chcesz mieć stan pośredni, w którym jest on gdzieś zapisany, ale nie nadpisuje źródła w $storeformularzu do momentu przesłania, musisz utworzyć taki element danych.

Roy J.
źródło
38
:valuekoniec v-model. Dziękuję Ci!
Connor Leech
4
Dziękuję ... naprawiłem też moje [vue warn]. Miałem szufladę nawigacji, która wymagała (tylko do odczytu) wartości prawda / fałsz, ale wstawiłem do niej model v.
GA
26

Tak powinno być.

W Twoim komponencie

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

W Twoim sklepie

export const store = new Vuex.Store({
         state:{
             name : "Stackoverflow"
         },
         getters: {
                 name: (state) => {
                     return state.name;
                 }
         }
}
OhhhThatVarun
źródło
1
Przepraszam za przywrócenie starej odpowiedzi, ale po co w tym przypadku używać gettera? Dlaczego nie zwrócić this.nameFromStore z mapState? Najwyraźniej działa równie dobrze.
Jake
@Jake W tym przykładzie to, co mówisz, jest słuszne. Ale jeśli chcesz manipulować zapisanymi danymi w sklepie, możesz to zrobić wewnątrz gettera, ale jeśli używasz this.nameFromStorebezpośrednio, nie możesz manipulować danymi.
OhhhThatVarun
1
Dzięki za wyjaśnienie :)
Jake
@Jake Nie ma problemu!
OhhhThatVarun
3

Dla mnie to się zmieniało.

this.name = response.data;

Do czego obliczony zwraca tak;

this.$store.state.name = response.data;
Ibn Rushd
źródło
0

Chcę tylko wspomnieć, dlaczego pojawia się to ostrzeżenie, za każdym razem, gdy tworzymy wartość obliczoną, która jest domyślnie pobierająca, jawnie musimy zdefiniować ustawiacze dla właściwości obliczonej,

jak wspomniano w dokumentacji VueJs, Computed Setter

Twoja obliczona właściwość będzie wyglądać następująco

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

Bardziej odpowiednim sposobem jest mapStatepobranie nazwy ze sklepu i inną opcję, którą definiujesz w swoim sklepie i używasz mapGettersdo wyodrębnienia nazwy ze sklepu,

Ważna informacja: gettery w sklepie są używane, gdy chcesz pobrać dane obliczone ze sklepu, wtedy w tym czasie definiujesz logikę w getterach, które otrzymują obliczone dane

przykład gettera

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

ten getter sprawdza twój stan dla aktywnego użytkownika i zwraca wartość true, jeśli zalogowałeś się i false, jeśli nie jesteś zalogowany,

później w całej aplikacji używamy mapGettersdo wyodrębnienia tej isLoggedInwłaściwości i dodania kontroli zgodnie z nią

mam nadzieję, że ktoś uzna tę pomoc za pełną :)

Hanzla Habib
źródło