programing

Vuejs 2, VUEX, 데이터 편집 시 데이터 바인딩

itsource 2022. 7. 2. 22:58
반응형

Vuejs 2, VUEX, 데이터 편집 시 데이터 바인딩

사용자 프로파일 섹션이 있는데 사용자가 정보를 편집할 수 있도록 허용하려고 합니다.vuex를 사용하여 사용자 프로파일 데이터를 저장하고 폼으로 가져옵니다.편집 양식은 userProfile 구성 요소의 하위 구성 요소에 있으며, 이 구성 요소는 데이터 저장을 VUEX에 커밋합니다.

따라서 폼에 VUEX의 데이터를 입력할 수 있지만 폼의 값을 변경하면 상위 컴포넌트의 값도 변경됩니다.

폼이 저장될 때까지 VUEX에 변경을 커밋하지 않기 때문에 데이터는 VUEX에 양방향으로 바인드됩니다.나는 이것이 불가능하다고 생각했다.이 경우 사용자가 일부 데이터를 변경한 후 실제로 "저장"을 클릭하지 않고 이동해도 VUEX 데이터는 여전히 변경되기 때문에 바람직하지 않습니다.

이것은 간단한 예입니다.실제로는 라우터 뷰를 사용하여 자 컴포넌트를 로드하고 있습니다.그렇지 않으면 데이터를 소품으로 전달합니다.아래와 같이 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;
        }
    }
}

여기 모든 게 잘 되고 있어요.

편집 양식을 가진 자식 구성 요소에서 다음과 같이 양식을 채웁니다.

<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>

vuex에서 바인딩되지 않는 솔루션을 찾는 경우 개체를 복제하고 v-model에 대해 커밋할 때보다 로컬 버전을 사용할 수 있습니다.

작성한 라이프 사이클 함수에서 다음을 수행합니다.

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, 그리고 당신에게는 분명하다.

장점: 편집한 정보를 저장할 준비가 될 때까지 다른 곳에 반영하지 않습니다.

단점: 일시적 변경을 반영해야 하는 경우(사용자 프로파일 미리보기 영역일 수 있음), 앱의 구조에 따라 동작하거나 동작하지 않을 수 있습니다.@input을 스테이트에 바인드 또는 저장할 수 있습니다.이 경우 temporaryUserProfile 오브젝트?

아직 Vue.js는 처음이고 2주 전부터 사용하기 시작했습니다.이것이 명확하고 올바르기를 바랍니다:)

이 문제는 mapGetters와 함께 v-model을 사용하여 발생합니다. 이렇게 하면 설명한 양방향 바인딩이 생성됩니다.간단한 해결책은 대신 가치를 사용하는 것입니다.

:value="profile.firstName"

이렇게 하면 폼은 필드의 로컬 복사본만 변경하고 변경 내용을 Vuex 저장소에 다시 푸시하지 않습니다.

@AfikDeri 솔루션은 훌륭하지만 얕은 복사본(예를 들어 중첩된 개체가 있는 경우 동작하지 않음)만 생성하여 이 문제를 해결하면 vuex 상태 개체를 직렬화하고 구문 분석할 수 있습니다.getUserDetails다음과 같습니다.

created (){
    this.profile = JSON.parse(JSON.stringify(this.$store.getters.getUserDetails));
}

언급URL : https://stackoverflow.com/questions/41862096/vuejs-2-vuex-data-binding-when-editing-data

반응형