在这里和其他地方,我已经阅读过多个类似的问题,但我无法弄清楚。
我有一个带有mapGetters
的表单,其输入值应根据Vuex状态进行更新:
...mapGetters({
show: "getShow"
}),
示例表单输入(我正在使用Bootstrap Vue)
<b-form-input
id="runtime"
name="runtime"
type="text"
size="sm"
v-model="show.runtime"
placeholder="Runtime"
></b-form-input>
然后在表单组件上有此方法:
async searchOnDB() {
var showId = this.show.showId;
if (!showId) {
alert("Please enter a showId");
return;
}
try {
await this.$store.dispatch("searchShowOnDB", showId);
} catch (ex) {
console.log(ex);
alert("error searching on DB");
}
},
以及此商店上的操作:
async searchShowOnDB({ commit, rootState }, showId) {
var response = await SearchAPI.searchShowOnDB(showId);
var show = {
show_start: response.data.data.first_aired,
runtime: response.data.data.runtime,
description: response.data.data.overview
};
//I'm updating the object since it could already contain something
var new_show = Object.assign(rootState.shows.show, show);
commit("setShow", new_show);
}
变异:
setShow(state, show) {
Vue.set(state, "show", show);
}
searchAPI:
export default {
searchShowOnDB: function (showId) {
return axios.get('/search/?id=' + showId);
},
}
一切正常,API调用已执行,我什至可以在Vue Devtools中看到Vuex更新状态,但是表单未更新。
一旦我在输入字段中输入内容或在Vue Devtools中点击commit
,表单字段show_start
,runtime
,description
就会全部更新。
此外,它可以正常工作并更新所有内容:
async searchShowOnDB({ commit, rootState }, showId) {
var show = {
show_start: "2010-03-12",
runtime: 60,
description: "something"
};
//I'm updating the object since it could already contain something
var new_show = Object.assign(rootState.shows.show, show);
commit("setShow", new_show);
}
我不知道该怎么办,我尝试了明确地解决Promises的尝试,删除了async / await并使用axios.get(...).then(...)
,四处移动...似乎无济于事。
答案 0 :(得分:1)
在15
的第/modules/search.js
行上,您正在Object.assign()
上使用rootState.search.show
。这会使search
的{{1}}属性发生突变(顺便说一句, 您应该只对内部突变进行突变 !)。在下面阅读原因。
然后您尝试触发突变。但猜猜怎么了? Vue看到它是相同的值,因此没有组件被通知,因为没有更改。这就是为什么您应该 从不 在突变之外进行突变!
因此,不要将值分配给操作中的状态,只需提交新的显示(用以下内容替换行state
:
15-16
在此处查看:https://codesandbox.io/s/sharp-hooks-kplp7?file=/src/modules/search.js
这会将 commit('setShow', show);
完全替换为state.show
。如果您只想将响应合并到当前show
中(以保留添加到当前state.show
中的一些自定义内容),则可以传播show
的内容并用{{ 1}}:
state.show
还请注意,您的突变不需要show
。您在任何突变的第一个参数中都具有commit("setShow", { ...rootState.search.show, ...show });
,这就是当前模块的Vue.set()
。因此,只需分配state
。
最后一点:当vuex变大时,您可能希望namespace模块,以避免任何名称冲突。
答案 1 :(得分:0)
在模板中使用的状态下,对象的所有道具都必须存在,或者应该为此类属性调用Vue.set。
state: {
show: {
runtime: null // <- add this line
}
},
您为整个对象调用Vue.set,但是它已经存在于状态中,并且您没有用新的替换它,而只是替换了props。在您的情况下,您有一个空对象,并使用Object.assign添加“运行时”属性。 同样,所有带有状态的操作都应在突变中完成
var new_show = {
runtime: response.data.url
};
commit("setShow", new_show);
...
mutations: {
setShow(state, new_show) {
Object.assign(state.show, new_show)
}
},