Vuejs 2, VUEX, привязка данных при редактировании данных

у меня есть профиль пользователя, и я пытаюсь разрешить пользователю редактировать свою информацию. Я использую vuex для хранения данных профиля пользователя и извлечения его в форму. Форма редактирования находится в дочернем компоненте компонента userProfile, который загружает сохранение данных, фиксирует его в VUEX.

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

Я не фиксировать изменения в VUEX, пока форма не будет сохранена, поэтому это означает, что данные привязаны к VUEX. У меня сложилось впечатление, что это невозможно. В этом случае это нежелательно, так как если пользователь изменяет некоторые данные, а затем переходит без фактического нажатия кнопки "Сохранить", данные VUEX по-прежнему изменяется.

Примечание, это упрощенный пример. Im фактически использует представление маршрутизатора для загрузки дочернего компонента, или я бы передал данные через реквизит. Я испытал загрузки edit-profile компонент прямо как показано ниже, и у меня такая же проблема.

пожалуйста, посмотрите код ниже, я не могу найти, почему данные отправляются обратно в магазин. Любая помощь очень ценится.

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

<template>
    <div class="content">
        <h1>{{getUserDetails.firstname}} {{getUserDetails.lastname}} </h1>
        <edit-profile></edit-profile>
    </div>
</template>
<script>
    import { mapGetters } from 'vuex';
    import EditProfile from './Edit.vue';

    export default {
        data() {
            return {
                // data
            }
        },
        created () {
            this.fetchData();
        },
        components: {
            EditProfile:EditProfile
        },
        computed: mapGetters([
            'getUserDetails'
        ]),
        methods: {
            fetchData: function () {
                var _this = this;
                // ajax call - then
                _this.$store.commit('setData', {
                    name: 'userDetails',
                    data: response.data.data.userDetails
                });
            }
        }
    }
</script>

это загружает результаты и хранит их в магазине, и отлично работает.

мой магазин это:

const store = new Vuex.Store({
    state: {
        userDetails: {}
    },
    mutations: {
        setData(state, payload){
            state[payload.name] = payload.data;
        }
    },
    getters: {
        getUserDetails: state => {
            return state.userDetails;
        }
    }
}

здесь все работает.

In мой дочерний компонент с формой редактирования, я заполняю форму следующим образом:

<template>
    <form>
        <label>Name</label>
        <input name="firstname" v-model="profile.firstname">
        <input name="lastname" v-model="profile.lastname">
        <button v-on:click="save">submit</button>
     </form>
</template>

<script>
import {mapGetters } from 'vuex';

export default {
    data() {
        return {
            profile:{}
        }
    },
    watch: {
        getUserDetails (newData){
            this.profile = newData;
        }
    },
    created (){
        this.profile = this.$store.getters.getUserDetails;
    },
    computed: mapGetters([
        'getUserDetails'
    ]),
    methods:{
        save (){
            var _this = this;
            // ajax call to POST this.profile then
            _this.$store.commit('setData', {
                name: 'userDetails',
                data: this.profile
            });
        }
    }
}
</script>

3 ответов


Если вы ищете решение без привязки с vuex, вы можете клонировать объект и использовать локальную версию для v-модели, чем при отправке фиксации.

в созданной функции жизненного цикла сделайте следующее:

created (){
    this.profile = Object.assign({}, this.$store.getters.getUserDetails);
},

Почему Я думаю он работает не так, как ожидалось для Вас: Вы получаете объект, привязывая его к локальному свойству. Затем, когда вы изменяете это локальное свойство, оно привязывается указателем объекта (/адресом памяти) к объекту хранилища. Создание нового объекта и установка свойств этого нового объекта на основе свойств объекта профиля пользователя состояния должны сделать трюк, так как новый объект будет иметь свой собственный адрес в памяти, будет указывать на другой место...

иллюстрации:

created (){
    // create a new object with {...}
    this.profile = {
        // assign values to properties of same name
        firstName: this.$store.getters.getUserDetails.firstName,
        lastName: this.$store.getters.getUserDetails.lastName,
    };
},

если эти свойства (firstName, lastName) являются объектами или массивами (все, к чему обращается указатель на адрес памяти), то это тоже не сработает.


так... то, что я, скорее всего, сделаю сам в этой ситуации, примерно так:

data() {
    return {
        firstName: '',
        lastName: ''
    }
},

это определяет локальные свойства. При загрузке данных вы заполняете локальные значения данными профиля, которые вы в магазине Vuex.

created() {
    let profile = this.$store.getters.getUserDetails;
    if (profile.firstName && profile.lastName) {
        this.firstName = profile.firstName;
        this.lastName = profile.lastName;
    }
},

затем при сохранении вы используете локальные переменные для обновления значений хранилища.

methods: {
    save() {
        let profile = {
            firstName: this.firstName,
            lastName: this.lastName
        };

        // ajax call to POST this.profile then
        this.$store.commit('setData', {
            name: 'userDetails',
            data: profile
        });
    }
}

Я пишу это с головы, так что здесь может быть ошибка или опечатка... Но я надеюсь, что, по крайней мере, моя логика верна ;-P и ясна для вас.

Pro: пока вы не будете готовы сохранить отредактированную информацию,вы не будете отражать ее нигде.

Con: если вам нужно чтобы отразить временные изменения (возможно, в области предварительного просмотра профиля пользователя), это может работать или не работать в зависимости от структуры приложения. Возможно, вы захотите привязать или сохранить @input к состоянию.temporaryUserProfile объект в этом случае?

Я все еще новичок в Vue.js, начал использовать его 2 недели назад. Надеюсь, это понятно и правильно :)


проблема вызвана использованием v-модели с mapGetters-это создает двустороннюю привязку, которую вы описали. Простым решением является использование value вместо:

:value="profile.firstName"

таким образом, форма изменяет только локальную копию поля и не возвращает изменения в хранилище Vuex.