等待 mapstate 中的数据完成加载
Wait for data in mapstate to finish loading
我在 Vuex
中存储了一个 userProfile
以便能够在我的整个项目中访问它。但是如果我想在 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
来解决这个问题,但没有任何效果。
即使您使 created
或 mounted
异步,它们也不会延迟您的组件呈现。它们只会延迟 await
.
之后的代码的执行
如果您不想在 userProfile
拥有 id
(或您的用户拥有的任何其他 属性 之前呈现模板的一部分(或全部),只需使用 v-if
<template v-if="userProfile.id">
<!-- your normal html here... -->
</template>
<template v-else>
loading user profile...
</template>
要在 userProfile
更改时执行代码,您可以在其中一个内部属性上放置一个 watcher。在您的情况下,这应该有效:
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 为这种模式提供了一个 built-in 解决方案,称为 Suspense。不幸的是,它只在少数几个地方被提及,它(还)没有被正确记录并且上面有一个标志 API 可能会改变。
但它非常棒,因为渲染条件可以与 parent 完全解耦。它可以包含在悬空 child 中。 child 声明的唯一内容是:“我正在加载” 或 “我已完成加载”。当所有悬念都准备好后,模板默认渲染。
此外,如果动态生成 children 并推送新的,则 parent 悬念切换回回退(加载)模板,直到加载新添加的 children。这是开箱即用的,您需要做的就是在 children.
中声明 mounted
async
简而言之,就是您对 Vue 2 的期望。
我在 Vuex
中存储了一个 userProfile
以便能够在我的整个项目中访问它。但是如果我想在 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
来解决这个问题,但没有任何效果。
即使您使 created
或 mounted
异步,它们也不会延迟您的组件呈现。它们只会延迟 await
.
如果您不想在 userProfile
拥有 id
(或您的用户拥有的任何其他 属性 之前呈现模板的一部分(或全部),只需使用 v-if
<template v-if="userProfile.id">
<!-- your normal html here... -->
</template>
<template v-else>
loading user profile...
</template>
要在 userProfile
更改时执行代码,您可以在其中一个内部属性上放置一个 watcher。在您的情况下,这应该有效:
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 为这种模式提供了一个 built-in 解决方案,称为 Suspense。不幸的是,它只在少数几个地方被提及,它(还)没有被正确记录并且上面有一个标志 API 可能会改变。
但它非常棒,因为渲染条件可以与 parent 完全解耦。它可以包含在悬空 child 中。 child 声明的唯一内容是:“我正在加载” 或 “我已完成加载”。当所有悬念都准备好后,模板默认渲染。
此外,如果动态生成 children 并推送新的,则 parent 悬念切换回回退(加载)模板,直到加载新添加的 children。这是开箱即用的,您需要做的就是在 children.
中声明 mounted
async
简而言之,就是您对 Vue 2 的期望。