Vuex: 작업 내에서 완전히 중첩된 상태 데이터를 변경할 수 없습니다.
스토어에서 몇 가지 데이터를 갱신하는 액션이 있습니다.액션은 다음과 같습니다.
setRoomImage({ state }, { room, index, subIndex, image }) {
state.fullReport.rooms[room].items[index].items[subIndex].image = image;
console.log(state.fullReport.rooms[room].items[index].items[subIndex])
},
이 모든 데이터는 동적이기 때문에 중첩된 값을 동적으로 변경해야 하며 속성을 직접 하드 코딩할 수 없습니다.데이터는 다음과 같습니다.
fullreport: {
rooms: {
abc: {
items: [
{
type: "image-only",
items: [
{
label: "Main Image 1",
image: ""
},
{
label: "Main Image 2",
image: ""
}
]
}
]
}
}
}
액션을 디스패치하면 콘솔에서 서브속성의 값이image
변환은 성공했지만 Chrome 내의 Vue DevTools에서 VueX 저장소에 액세스해도 값이 변경되지 않습니다.콘솔 출력은 다음과 같습니다.
누가 왜 이런 일이 일어나는지 말해줄래?데이터가 정상적으로 변경되고 있는 것은 알고 있습니다만, 왠지 상태가 표시되지 않기 때문에 컴포넌트가 재생되지 않습니다.
저도 한번 써봤어요.Vue.set
간단한 임무 대신, 그러나 여전히 운이 없다: (
Vue.set(
state.fullReport.rooms[room].items[index].items[subIndex],
"image",
image
);
편집:
David Gard의 대답에 따라 다음을 시도했습니다.
저도 Lodash를 사용하고 있습니다._
(객체의 전체 복사본을 만드는 것이 좋지 않다는 것을 알고 있습니다.) 이것이 변환 코드 블록입니다.
let fullReportCopy = _.cloneDeep(state.fullReport);
fullReportCopy.rooms[room].items[index].items[subIndex].image = image;
Vue.set(state, "fullReport", fullReportCopy);
이제 계산된 속성에서state.fullReport
의존관계입니다.console.log
계산된 속성이 다시 검색될 때마다 문자열을 출력합니다.
이 변환을 커밋할 때마다 계산된 속성에 문자열이 기록되지만 수신 상태는 변경되지 않습니다.Vue.set
상태가 변경되었음을 계산 속성에 알릴 뿐 실제로는 변경되지 않습니다.따라서 컴포넌트의 UI는 변경되지 않습니다.
코멘트에서도 언급되어 있듯이, 스토어에서 깊게 중첩된 상태를 유지하면, 금방 복잡해집니다.
문제는 어레이와 오브젝트를 두 가지 방법으로 채워야 하기 때문에 네이티브 메서드에 액세스할 필요가 있는지 여부를 고려해야 한다는 것입니다.안타깝게도 Vuex는 아직 사후 대응 맵을 지원하지 않습니다.
이와는 별도로 여러 중첩된 수준의 속성을 동적으로 설정해야 하는 프로젝트도 처리합니다.이를 위한 한 가지 방법은 각 속성을 재귀적으로 설정하는 것입니다.
예쁘지는 않지만 효과가 있습니다.
function createReactiveNestedObject(rootProp, object) {
// root is your rootProperty; e.g. state.fullReport
// object is the entire nested object you want to set
let root = rootProp;
const isArray = root instanceof Array;
// you need to fill Arrays with native Array methods (.push())
// and Object with Vue.set()
Object.keys(object).forEach((key, i) => {
if (object[key] instanceof Array) {
createReactiveArray(isArray, root, key, object[key])
} else if (object[key] instanceof Object) {
createReactiveObject(isArray, root, key, object[key]);
} else {
setReactiveValue(isArray, root, key, object[key])
}
})
}
function createReactiveArray(isArray, root, key, values) {
if (isArray) {
root.push([]);
} else {
Vue.set(root, key, []);
}
fillArray(root[key], values)
}
function fillArray(rootArray, arrayElements) {
arrayElements.forEach((element, i) => {
if (element instanceof Array) {
rootArray.push([])
} else if (element instanceof Object) {
rootArray.push({});
} else {
rootArray.push(element);
}
createReactiveNestedFilterObject(rootArray[i], element);
})
}
function createReactiveObject(isArray, obj, key, values) {
if (isArray) {
obj.push({});
} else {
Vue.set(obj, key, {});
}
createReactiveNestedFilterObject(obj[key], values);
}
function setValue(isArray, obj, key, value) {
if (isArray) {
obj.push(value);
} else {
Vue.set(obj, key, value);
}
}
만약 누군가 더 똑똑한 방법을 가지고 있다면 나는 그것을 듣고 싶어!
편집:
위의 게시된 솔루션을 사용하는 방법은 다음과 같습니다.
// in store/actions.js
export const actions = {
...
async prepareReactiveObject({ commit }, rawObject) {
commit('CREATE_REACTIVE_OBJECT', rawObject);
},
...
}
// in store/mutations.js
import { helper } from './helpers';
export const mutations = {
...
CREATE_REACTIVE_OBJECT(state, rawObject) {
helper.createReactiveNestedObject(state.rootProperty, rawObject);
},
...
}
// in store/helper.js
// the above functions and
export const helper = {
createReactiveNestedObject
}
댓글에 있는 모범 사례를 제외하고.
필요한 것은 개체가 변경될 때 Vue에 지시하는 것입니다(복잡한 개체는 반응하지 않음).Vue.set을 사용합니다.개체 전체를 설정해야 합니다.
Vue.set(
state,
"fullReport",
state.fullReport
);
문서: https://vuejs.org/v2/api/ #Vue-set
언급URL : https://stackoverflow.com/questions/57907075/vuex-cant-change-deeply-nested-state-data-inside-actions
'IT이야기' 카테고리의 다른 글
(getter 없이) vuex 상태 속성에 직접 액세스하는 것은 잘못된 관행입니다. 그 이유는 무엇입니까? (0) | 2022.06.13 |
---|---|
Vuex: 컴포넌트 내에서 액션을 사용하는 것과 처리를 사용하는 것의 차이점 (0) | 2022.06.13 |
Java 8 Date Time API(java.time)와 Joda-Time의 차이점 (0) | 2022.06.13 |
왜 수학 도서관을 C로 링크해야 하죠? (0) | 2022.06.13 |
Nuxt.js - 레이아웃 내 컴포넌트 사용방법 (0) | 2022.06.13 |