4

我已经存储了一个userProfileinVuex以便能够在我的整个项目中访问它。但是如果我想在created()钩子中使用它,配置文件还没有加载。该对象存在,但其中没有存储数据。至少在页面的初始加载时。如果我稍后访问它(例如通过单击按钮),一切都会完美运行。有没有办法等待数据完成加载?

以下是如何userProfile设置Vuex

mutations: {
    setUserProfile(state, val){
      state.userProfile = val
    }
},
actions: {
    async fetchUserProfile({ commit }, user) {
      // fetch user profile
      const userProfile = await fb.teachersCollection.doc(user.uid).get()
  
      // set user profile in state
      commit('setUserProfile', userProfile.data())
    },
}

这是我要访问它的代码:

<template>
<div>
  <h1>Test</h1>
  {{userProfile.firstname}}
  {{institute}}
</div>
</template>


<script>
import {mapState} from 'vuex';

export default {
  data() {
    return {
      institute: "",
    }
  },
  computed: {
      ...mapState(['userProfile']),
  },
  created(){
    this.getInstitute();
  },

  methods: {
    async getInstitute() {
      console.log(this.userProfile); //is here still empty at initial page load

      const institueDoc = await this.userProfile.institute.get();
      if (institueDoc.exists) {
        this.institute = institueDoc.name;
      } else {
        console.log('dosnt exists') 
      }
      
    }
  }
}
</script>

通过登录控制台,我发现问题出在代码运行的顺序上。首先,运行该方法getInstitute,然后action运行mutation​​. 我试图添加一个loaded参数并尝试await解决这个问题,但没有任何效果。

4

1 回答 1

3

即使您制作createdmounted异步,它们也不会延迟您的组件渲染。它们只会延迟 . 之后的代码的执行await

如果您不想在userProfile拥有id(或您的用户拥有的任何其他属性)之前呈现模板的一部分(或全部),只需使用v-if

<template v-if="userProfile.id">
  <!-- your normal html here... -->
</template>
<template v-else>
   loading user profile...
</template>

要在更改时执行代码userProfile,您可以在其内部属性之一上放置一个观察程序。在您的情况下,这应该有效:

export default {
  data: () => ({
    institute: ''
  }),
  computed: {
    ...mapState(['userProfile']),
  },
  watch: {
    'userProfile.institute': {
      async handler(institute) {
        if (institute) {
          const { name } = await institute.get();
          if (name) {
            this.institute = name;
          }
        } 
      },
      immediate: true
    }
  }
}

旁注:Vue 3 为这种模式提供了一个内置的解决方案,称为Suspense。不幸的是,它只在少数地方被提及,它(还)没有被正确记录,并且有迹象表明 API 可能会改变。
但它非常棒,因为渲染条件可以与父级完全解耦。它可以包含在悬浮的孩子中。孩子唯一声明的是:“I'm current loading”“I'm done loading”。当所有 suspensibles 都准备好后,就会渲染模板默认值。
此外,如果子项是动态生成的并推送了新的子项,则父悬念切换回回退(加载)模板,直到加载了新添加的子项。这是开箱即用的,您需要做的就是mounted在孩子中声明异步。
简而言之,您对 Vue 2 的期望。

于 2021-02-07T17:35:15.553 回答