我有一个Vuex商店,在名为users的模块状态下有一个名为data的对象。此对象将用户ID映射到用户,并且它开始为空。
然后我有一个消息列表组件,它使用名为authorId的传递属性呈现消息组件。此消息将使用id尝试通过搜索商店中的数据对象来获取作者的电子邮件。如果找不到它,它将调度一个动作,该动作将从服务器获取用户并提交变异以将id和用户添加到商店中的数据对象。请注意,现在每条消息都具有相同的authorId,并且服务器提取逻辑按预期工作。
用户模块
state: { data: {} },
mutations: {
setUser(state, user) {
Vue.set(state.data, user._id, user);
},
},
actions: {
fetchUser({ commit }, id) {
userService.find({ _id: id }).then((response) => {
commit('setUser', response.data[0]);
});
}
消息组件
<template>
<div class="message">
<strong v-if="author">{{author.email}}</strong>: {{text}}
</div>
</template>
<script>
export default {
name: 'messages',
props: ['text', 'authorId'],
created() {
this.resolveAuthor();
},
computed: {
author() {
return this.$store.state.users.data[this.authorId];
},
},
methods: {
resolveAuthor() {
if (!this.author) this.$store.dispatch('fetchUser', this.authorId);
},
};
</script>
预期的行为是只看到一个setUser变异,因为第一个消息组件实例将获取并填充存储,下一个实例将使用该存储的值。我看到每个消息有一个突变,这意味着在created()或mounted()中对this.author的调用总是未定义的,也许我会在第一个消息中预期这个,但是因为已经填充了存储,所以不会在下一个消息中。 p>
在每个消息实例的每个created()或mounted()中执行console.log(Object.keys(this。$ store.state.users.data))会显示数据对象为空但我可以看到它有一个key(authorId)和vue dev-tools中的用户值,以及我的console.log(此。$ store.state.users.data)。
此外,如果在模板中我呈现{{this.user}},它将在每条消息上正确打印数据。此外,如果我重新保存任何文件,热重新加载现在将打印所有console.log(Object.keys(此。$ store.state.users.data))我之前再次执行但现在显示我期望的键和值显示一个空对象。
编辑2018-10-24 我希望工作资料库可以帮助某人:https://github.com/niklabaz/chatter
答案 0 :(得分:2)
我认为你在那里遇到了竞争条件。您正在循环和创建组件,然后在创建每个组件(消息)时,您希望获得创建了msg的用户。现在我认为发生了什么是你创建第一个组件并且它没有检测到数据中的用户,因此它试图获取它但是在该用户通过api之前(即使它&#39;几个ms)你渲染另一个组件和data.users仍然没有填充,它调度另一个api请求。请记住,vue不会等待一个api请求返回数据以在循环中呈现另一个组件。如果这是真的并且我是正确的,那么您需要重新构建组件结构或者至少以不同的方式获取用户。
修改强>
我的建议是修补你的服务器端代码,以便它发送一个用户对象(或至少是他们的uname和id)作为每个消息对象的一部分。即使您不使用ORM,也可以加入具有user_id FK和用户表的msg表。然后,您在父组件中获取所有这些数据,然后当您循环浏览消息时,您将获得所需的所有用户信息。