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.