Vuex - вычисленное свойство «name» было назначено, но у него нет установщика.

111

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

Ответы:

193

Если вы собираетесь v-modelиспользовать вычисляемый объект, ему понадобится сеттер . Все, что вы хотите, чтобы он делал с обновленным значением (возможно, записываете его $store, учитывая, что ваш получатель извлекает его), вы делаете в сеттере.

Если запись обратно в магазин происходит через отправку формы, вы этого не хотите v-model, вы просто хотите установить :value.

Если вы хотите иметь промежуточное состояние, в котором оно где-то сохраняется, но не перезаписывает источник при $storeотправке формы до, вам необходимо создать такой элемент данных.

Рой Дж.
источник
39
:valueзакончился v-model. Спасибо!
Коннор Лич
4
Спасибо ... исправлено и мое [vue warn]. У меня был ящик навигации, который требовал (только для чтения) значения true / false, но я добавил к нему v-модель.
GA
29

Так и должно быть.

В вашем компоненте

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;
                 }
         }
}
OhhhThatVarun
источник
1
Извините за восстановление вашего старого ответа, но зачем в этом случае использовать геттер? Почему бы не вернуть this.nameFromStore из mapState? Очевидно, это работает так же хорошо.
Джейк,
@Jake Для данного примера то, что вы говорите, верно. Но если вы хотите манипулировать сохраненными данными в магазине, вы можете сделать это внутри геттера, но если вы используете this.nameFromStoreнапрямую, вы не можете манипулировать данными.
OhhhThatVarun
1
Спасибо за разъяснения :)
Джейк
@ Джейк Нет проблем!
OhhhThatVarun
4

Для меня это менялось.

this.name = response.data;

К чему вычисленное возвращается так;

this.$store.state.name = response.data;
Ибн Рушд
источник
-1

Я просто хочу упомянуть, почему появляется это предупреждение: всякий раз, когда мы создаем вычисляемое значение, оно является геттером по умолчанию, нам явно нужно определить сеттеры для вычисляемого свойства,

как указано в документации VueJs, Computed Setter

ваше вычисленное свойство будет выглядеть так

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

Более подходящий способ - это использовать mapStateдля получения имени из магазина и другой вариант, который вы определяете в своем магазине и используете mapGettersдля извлечения имени из магазина,

Важно знать: геттеры в магазине используются, когда вы хотите получить вычисленные данные из хранилища, тогда вы определяете логику в геттерах, которые получают вычисленные данные.

пример геттера

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

этот геттер проверяет ваше состояние на наличие активного пользователя и возвращает true, если loggedIn, и false, если не loggedIn,

позже во всем приложении мы mapGettersизвлекаем это isLoggedInсвойство и добавляем проверки в соответствии с этим

надеюсь, что кто-то найдет эту помощь полной :)

Ханзла Хабиб
источник