在使用 Vue + Vuex 渲染之前无法获取对象的 属性 状态

Cannot get object’s property in state before render using Vue + Vuex

我有一个 Vuex 存储,其中包含一个名为 data 的对象,处于名为 users 的模块状态。此对象将用户 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 的调用始终未定义,也许我会在第一条消息中看到这一点,但在下一条消息中不会,因为商店已经填充。

在每个消息实例的每个 created() 或 mounted() 中执行 console.log(Object.keys(this.$store.state.users.data)) 显示数据对象为空,但我可以在 vue 开发工具中看到它有一个键 (authorId) 和用户值,如果我 console.log(this.$store.state.users.data).

此外,如果在模板中呈现 {{this.user}},它将在每条消息上正确打印数据。此外,如果我重新保存任何文件,热重载现在将打印我之前做过的所有 console.log(Object.keys(this.$store.state.users.data)) 但现在显示的键和值我expect 而不是显示空对象。

编辑 2018-10-24 我希望工作存储库对某人有所帮助:https://github.com/niklabaz/chatter

我认为您那里存在竞争条件。您正在循环并创建组件,然后当您创建每个组件(消息)时,您希望获得创建消息的用户。现在我认为正在发生的事情是你创建了第一个组件并且它没有检测到数据中的用户所以它试图获取它但是在该用户通过 api 获得之前(即使是几毫秒也需要时间)您渲染另一个组件,但 data.users 仍未填充,它会调度另一个 api 请求。请记住,vue 不会等待 api 对 return 数据的请求来循环渲染另一个组件。如果这是真的并且我是正确的,您将需要重组您的组件结构或至少以不同的方式获取用户。

编辑

我的建议是修改您的服务器端代码,以便它发送一个用户对象(或至少他们的 uname 和 id )作为每个消息对象的一部分。即使您不使用 ORM,您也可以加入与用户 table 有 user_id FK 的消息 table。然后你在父组件中获取所有这些数据,然后当你遍历消息时你将拥有你需要的所有用户信息。