我有以下 vuex 状态的初始结构(在 VueJS 项目中):
state: {
level1prop: null
}
然后我动态地更改它,并将其变异为以下结构:
state: {
level1prop: {
level2prop: {
level3prop: {
"customKey1": { /* this is some object 1 */ },
"customKey2": { /* this is some object 2 */ },
...
}
}
}
}
然后我将在 level3prop
下添加 "customKeyN": {/* this is some object N */}
对我来说重要的是每次更改触发观察者,它正在观察状态对 level1prop
的更改。
最初,在我的突变中,我通过以下方式进行更新:
if (!state.hasOwnProperty("level1prop"))
state["level1prop"] = {};
else if (state["level1prop"] === null || state["level1prop"] === undefined)
state["level1prop"] = {};
if (!state["level1prop"].hasOwnProperty("level2prop"))
state["level1prop"]["level2prop"] = {};
else if (state["level1prop"]["level2prop"] === null || state["level1prop"]["level2prop"] === undefined)
state["level1prop"]["level2prop"] = {};
if (!state["level1prop"]["level2prop"].hasOwnProperty("level3prop"))
state["level1prop"]["level2prop"]["level3prop"] = {};
else if (state["level1prop"]["level2prop"]["level3prop"] === null || state["level1prop"]["level2prop"]["level3prop"] === undefined)
state["level1prop"]["level2prop"]["level3prop"] = {};
let payloadObj = { "customKey1": { /* this is some object 1 */ } };
state["level1prop"]["level2prop"]["level3prop"] = payloadObj;
这是按照我想要的方式创建结构,但未触发更改观察者。遵循 here 的建议我将我的代码重构为几种不同的方式,但没有一种方式会触发更改。这是我尝试过的最新选项的示例:
if (!state.hasOwnProperty("level1prop"))
state = Object.assign(state, { "level1prop" : {} });
else if (state["level1prop"] === null || state["level1prop"] === undefined)
state = Object.assign(state, { "level1prop" : {} });
if (!state["level1prop"].hasOwnProperty("level2prop"))
state["level1prop"] = Object.assign(state["level1prop"], { "level2prop" : {} });
else if (state["level1prop"]["level2prop"] === null || state["level1prop"]["level2prop"] === undefined)
state["level1prop"] = Object.assign(state["level1prop"], { "level2prop" : {} });
if (!state["level1prop"]["level2prop"].hasOwnProperty("level3prop"))
state["level1prop"]["level2prop"] = Object.assign(state["level1prop"]["level2prop"], { "level3prop" : {} });
else if (state["level1prop"]["level2prop"]["level3prop"] === null || state["level1prop"]["level2prop"]["level3prop"] === undefined)
state["level1prop"]["level2prop"] = Object.assign(state["level1prop"]["level2prop"], { "level3prop" : {} });
let payloadObj = { "customKey 1": { /* this is some object 1 */ } };
state["level1prop"]["level2prop"]["level3prop"] = Object.assign(state["level1prop"]["level2prop"]["level3prop"], payloadObj);
同样,这正在创建我需要的结构,但仍未触发观察者。我尝试过但未触发更改的其他一些选项是:
...
state["level1prop"]["level2prop"]["level3prop"] = Object.assign({}, state["level1prop"]["level2prop"]["level3prop"], payloadObj);
...
和
...
Object.assign(state["level1prop"]["level2prop"]["level3prop"], payloadObj);
...
在具有如此多嵌套级别的如此复杂的对象状态中,是否有任何方法能够触发观察者进行更改?
最佳答案
如文档中所述 Object Change Detection Caveats部分,你最好使用专门设计的 Vue setter Vue.set
稍后将子级别添加到您的状态。
然后确保您的观察者指定了 deep
选项,以便在您的子级别更改时正确触发它。
const store = new Vuex.Store({
state: {
level1prop: null,
},
});
const state = store.state;
if (!state["level1prop"])
Vue.set(state, "level1prop", {})
if (!state["level1prop"]["level2prop"])
Vue.set(state["level1prop"], "level2prop", {})
if (!state["level1prop"]["level2prop"]["level3prop"])
Vue.set(state["level1prop"]["level2prop"], "level3prop", {})
let payloadObj = {
"customKey1": {
hello: "world",
},
};
state["level1prop"]["level2prop"]["level3prop"] = payloadObj;
setTimeout(() => {
// Change an already existing key.
state["level1prop"]["level2prop"]["level3prop"].customKey1.hello = "too";
}, 1000);
setTimeout(() => {
// To add or remove keys, make sure to use again Vue.set or Vue.delete.
state["level1prop"]["level2prop"]["level3prop"].customKey1.hello = "too";
Vue.set(state["level1prop"]["level2prop"], "level3propSibling", {
hi: "again",
});
}, 2000);
new Vue({
store: store,
watch: {
"$store.state": {
// Make sure you specify the `deep` option
deep: true,
handler() {
console.log(store.state);
},
},
},
});
<script src="https://unpkg.com/vue@2"></script>
<script src="https://unpkg.com/vuex@3"></script>
关于vue.js - 在 VueJs 的对象中添加新属性时如何触发更改?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51411566/