vuejs/변수 값을 사용하여 양방향 바인딩 제한 다른 변수 수정 시 변경
mapGetter를 통해 내 스토어에서 얻은 클라이언트 목록을 포함하는 'client-display' 컴포넌트가 있습니다.목록 위에 'v-for'를 사용하여 모든 항목을 'v-for-panel'로 표시하므로 클라이언트 = 패널 하나가 됩니다.이들 패널의 헤더에는 클라이언트의 소품으로 전달된 '편집-삭제' 컴포넌트가 있습니다.이 "edit-delete"는 기본적으로 payload에 대한 해당 아이콘을 클릭하면 "edit" 또는 "delete" 이벤트만 발생합니다.편집 아이콘을 클릭하면 편집 이벤트가 '클라이언트 디스플레이'에 캐치되므로 클라이언트를 '클라이언트'라는 변수에 할당할 수 있습니다(좀 헷갈리긴 하지만).이 변수를 내 대화 상자에 소품으로 전달하고 이 대화 상자를 사용하여 클라이언트를 편집합니다.
문제는 클라이언트를 편집할 때 올바르게 편집되지만 [취소]를 클릭하면 UI에서 발생한 내용을 되돌릴 수 없다는 것입니다.오래된 값을 가진 오브젝트를 유지하고 취소 이벤트에서 리셋하려고 했지만, 어떤 일이 있어도 오브젝트에 보관하려고 하는 기준값마저 바뀌어 가장 놀라운 일이었습니다.이를 위해 새로운 개체를 시작하고 값을 수동으로 할당하거나 Object.assign()을 사용하는 등 여러 가지 작업을 시도했습니다.이 모든 것을 풀려고 여러 가지 방법을 시도해봤지만 잘 되지 않았다.변경 내용이 UI에 표시되기 전에 스토어에서 커밋될 때까지 기다리거나 참조 개체를 사용하여 '취소' 이벤트의 값을 재설정할 수 있습니다.
코드와 관련된 부분은 다음과 같습니다(읽기 쉽게 하기 위해 많은 것을 제거했지만 필요한 것은 모두 갖추어져 있습니다).
내 스토어의 클라이언트 모듈
이 부분은 고객을 제대로 확보했기 때문에 잘 작동한다고 생각합니다만, 뭔가 바인딩되어 있어서는 안 됩니다.
const state = {
clients: null,
};
const getters = {
[types.CLIENTS] : state => {
return state.clients;
},
};
const mutations = {
[types.MUTATE_LOAD]: (state, clients) => {
state.clients = clients;
},
};
const actions = {
[types.FETCH]: ({commit}) => {
clientsCollection.get()
.then((querySnapshot) => {
let clients = querySnapshot.docs.map(doc => doc.data());
commit(types.MUTATE_LOAD, clients)
}).catch((e) => {
//...
});
},
}
export default {
state,
getters,
mutations,
...
}
ClientsDisplay 컴포넌트
<template>
<div>
<div>
<v-expansion-panels>
<v-expansion-panel
v-for="c in clientsDisplayed"
:key="c.name"
>
<v-expansion-panel-header>
<div>
<h2>{{ c.name }}</h2>
<edit-delete
:element="c"
@edit="handleEdit"
@delete="handleDelete"
/>
</div>
</v-expansion-panel-header>
<v-expansion-panel-content>
//the client holder displays the client's info
<client-holder
:client="c"
/>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</div>
<client-add-dialog
v-model="clientPopup"
:client="client"
@cancelEdit="handleCancel"
/>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import * as clientsTypes from '../../../../store/modules/clients/types';
import ClientDialog from './ClientDialog';
import EditDelete from '../../EditDelete';
import ClientHolder from './ClientHolder';
import icons from '../../../../constants/icons';
export default {
name: 'ClientsDisplay',
components: {
ClientHolder,
ClientAddDialog,
EditDelete,
},
data() {
return {
icons,
clientPopup: false,
selectedClient: null,
client: null,
vueInstance: this,
}
},
created() {
this.fetchClients();
},
methods: {
...mapGetters({
'stateClients': clientsTypes.CLIENTS,
}),
...mapActions({
//this loads my clients in my state for the first time if needed
'fetchClients': clientsTypes.FETCH,
}),
handleEdit(client) {
this.client = client;
this.clientPopup = true;
},
handleCancel(payload) {
//payload.uneditedClient, as defined in the dialog, has been applied the changes
},
},
computed: {
isMobile,
clientsDisplayed() {
return this.stateClients();
},
}
}
</script>
EditDelete 컴포넌트
<template>
<div>
<v-icon
@click.stop="$emit('edit', element)"
>edit</v-icon>
<v-icon
@click.stop="$emit('delete', element)"
>delete</v-icon>
</div>
</template>
<script>
export default {
name: 'EditDelete',
props: ['element']
}
</script>
ClientDialog 컴포넌트
주의사항: headerTitle은 클라이언트 이름이 변경되어도 그대로 유지됩니다.
<template>
<v-dialog
v-model="value"
>
<v-card>
<v-card-title
primary-title
>
{{ headerTitle }}
</v-card-title>
<v-form
ref="form"
>
<v-text-field
label="Client name"
v-model="clientName"
/>
<address-fields
v-model="clientAddress"
/>
</v-form>
<v-card-actions>
<v-btn
@click="handleCancel"
text
>Annuler</v-btn>
<v-btn
text
@click="submit"
>Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import AddressFields from '../../AddressFields';
export default {
name: 'ClientDialog',
props: ['value', 'client'],
components: {
AddressFields,
},
data() {
return {
colors,
clientName: '',
clientAddress: { province: 'QC', country: 'Canada' },
clientNote: '',
uneditedClient: {},
}
},
methods: {
closeDialog() {
this.$emit('input', false);
},
handleCancel() {
this.$emit('cancelEdit', { uneditedClient: this.uneditedClient, editedClient: this.client})
this.closeDialog();
},
},
computed: {
headerTitle() {
return this.client.name
}
},
watch: {
value: function(val) {
// I watch there so I can reset the client whenever I open de dialog
if(val) {
// Here I try to keep an object with the value of this.client before I edit it
// but it doesn't seem to work as I intend
Object.assign(this.uneditedClient, this.client);
this.clientName = this.client.name;
this.clientContacts = this.client.contacts;
this.clientAddress = this.client.address;
this.clientNote = '';
}
}
}
}
</script>
데이터의 개별 복사본을 유지하려면 klona와 같은 항목을 사용하여 개체의 심층 복사본을 수행해야 합니다.Object.assign을 사용하는 것은 얕은 복사이며 참조 값의 변경으로부터 보호되지 않습니다.
언급URL : https://stackoverflow.com/questions/63385761/limiting-the-two-way-binding-with-vuejs-variable-values-change-when-modifying
'programing' 카테고리의 다른 글
계산된 속성이 에 할당되었지만 설정자가 없습니다. (0) | 2022.08.31 |
---|---|
Java LinkedHashMap이 처음 또는 마지막 항목을 가져옵니다. (0) | 2022.08.30 |
vuetify는 이미지가 로딩되지 않지만 prop에는 url이 표시되어 있습니다. (0) | 2022.08.30 |
Vuex가 다른 어레이를 전달 (0) | 2022.08.30 |
C의 비트 배열 정의 및 조작 방법 (0) | 2022.08.30 |