Vuex - ім'я обчисленої властивості було призначено, але воно не має сеттера


108

У мене є компонент з деякою валідацією форми. Це багатоетапна форма оформлення замовлення. Код нижче - для першого кроку. Я хотів би підтвердити, що користувач вводив якийсь текст, зберігає його ім’я в глобальному стані, а потім надсилає на наступний крок. Я використовую vee-validate та 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>

У мене є магазин для обробки стану замовлення та запису назви. Зрештою, я хотів би надіслати всю інформацію з багатокрокової форми на сервер.

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

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

    }
  },

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

Коли я запускаю цей код, я отримую помилку Computed property "name" was assigned to but it has no setter.

Як я прив'язую значення з поля імені до глобального стану? Я хотів би, щоб це було наполегливим, так що навіть якщо користувач повернеться крок назад (після натискання кнопки "Наступний крок"), він побачить ім'я, яке вони ввели на цьому кроці


1
Окрім відповіді Роя Дж, схоже, що використання v-forна обчислювальній машині без сеттера також загрожує цим попередженням.
jsiegal

Відповіді:


192

Якщо ви збираєтеся v-modelв обчислювальний, йому потрібен сетер . Що б ви не хотіли, щоб це було пов'язано з оновленим значенням (можливо, напишіть його до $store, враховуючи, що саме це отримує ваш отримувач), яке ви робите в сетері.

Якщо повернення його назад до магазину відбувається за допомогою надсилання форми, ви цього не хочете v-model, ви просто хочете встановити :value.

Якщо ви хочете мати проміжний стан, де він десь зберігається, але не перезаписує джерело до $storeмоменту подання форми, вам потрібно створити такий елемент даних.


37
:valueнад v-model. Дякую!
Connor Leech

4
Дякую ... виправили і мою [vue warn]. У мене був ящик навігації, який вимагав (лише для читання) значення true / false, але я поставив йому v-модель.
GA

26

Це повинно бути таким.

У своєму компоненті

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

У вашому магазині

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

1
Вибачте за відродження старої вашої відповіді, але навіщо використовувати геттер у цьому випадку? Чому б не повернути this.nameFromStore з mapState? Це працює так само добре, мабуть.
Джейк

@Jake Для цього наведеного прикладу те, що ви говорите, правильно. Але коли ви хочете маніпулювати збереженими даними в магазині, ви можете зробити це всередині getter, але якщо ви використовуєте this.nameFromStoreбезпосередньо, ви не можете маніпулювати даними.
OhhhThatVarun

1
Дякую за уточнення :)
Джейк

@Jake Немає проблем!
OhhhThatVarun

3

Для мене це змінювалося.

this.name = response.data;

До чого обчислюється повертає так;

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

0

Я просто хочу зазначити, чому це попередження з’являється, коли ми створюємо обчислене значення, яке воно за замовчуванням стає getter, нам явно потрібно визначити сеттери для обчисленої властивості,

як зазначено в документації VueJs, Computed Setter

ваше обчислене властивість буде виглядати приблизно так

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

Більш підходящим способом є те, що ви використовуєте mapStateдля отримання імені з магазину, а також інший варіант, який ви визначаєте в магазині getter і використовуєте mapGettersдля вилучення імені з магазину,

Важливо знати: що в магазині використовуються, коли ви хочете отримати обчислювані дані з магазину, тоді ви визначаєте логіку в гетерах, які отримують ваші обчислені дані

приклад геттера

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

цей отримувач перевірить ваш стан на активного користувача та поверне справжнє значення, якщо увійшли в систему, і помилково, якщо вони не входили,

пізніше у всій програмі ми використовуємо mapGettersдля вилучення цього isLoggedInвластивості та додавання чеків відповідно до цього

сподіваюся, що хтось знайде цю допомогу повної :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.