如何在带有 vuex 的 vue 生命周期钩子中使用 async/await?
Posted
技术标签:
【中文标题】如何在带有 vuex 的 vue 生命周期钩子中使用 async/await?【英文标题】:How to use async/await in vue lifecycle hooks with vuex? 【发布时间】:2021-04-14 19:03:20 【问题描述】:当我在 Mounted() 生命周期钩子中调度 App.vue 组件中的操作时,它会在其他组件加载后运行。我在我的操作中使用 async/await 并挂载了生命周期钩子。
App.vue 文件
methods:
...mapActions(
setUsers: "setUsers",
),
,
async mounted()
try
await this.setUsers();
catch (error)
if (error)
console.log(error);
,
action.js 文件:
async setUsers(context)
try
const response = await axios.get('/get-users');
console.log('setting users');
if (response.data.success)
context.commit('setUsers',
data: response.data.data,
);
catch (error)
if (error)
throw error;
,
在用户列表组件中,我需要从 vuex 获取用户。所以我使用 mapGetters 来获取用户列表。
...mapGetters(
getUsers: "getUsers",
),
mounted()
console.log(this.getUsers);
,
但问题是在控制台记录this.getUsers
之后运行“设置用户”控制台登录。
在用户列表组件中,我可以在模板中使用 getUsers,但是当我尝试控制台日志 this.getUsers 时,它什么也没提供。
如何在运行任何其他组件之前运行app.vue
文件?
【问题讨论】:
【参考方案1】:您在组件中正确使用了异步等待。重要的是要了解async await
不会延迟组件的执行,并且您的组件仍将呈现并通过不同的生命周期钩子,例如mounted
。
async await
所做的是推迟 当前上下文 的执行,如果你在函数中使用它,await
之后的代码将在 promise 解决后发生,并且在您的情况下,您在 created
生命周期钩子中使用它,这意味着 mounted
生命周期钩子中的代码是一个函数,将在等待后得到解决。
因此,您要做的是确保仅在收到数据时才渲染组件。
这是怎么做的:
-
如果组件是父组件的子组件,可以使用
v-if
,然后数据来的时候设置数据为true,像这样:
data()
return
hasData: false,
async mounted()
const users = await fetchUsers()
this.hasData = true;
<SomeComponent v-if="hasData" />
-
如果组件不是父组件的子组件,您可以使用
watcher
让您知道组件何时渲染。使用watch
时要小心,因为每次更改都会发生。
一个简单的经验法则是使用 watch 和不经常变化的变量,如果你得到的数据大部分是只读的,你可以使用数据,如果不是,你可以向 Vuex 添加一个属性,例如 @ 987654332@.
以下是如何执行此操作的示例:
data:
return
hasData: false,
,
computed:
isLoading()
return this.$store.state.app.users;
,
watch:
isLoading(isLoading)
if (!isLoading)
this.hasData = true;
<SomeComponent v-if="hasData" />
【讨论】:
【参考方案2】:问题:您是否希望每次加载应用时都运行await this.setUsers();
(无论显示哪个页面/组件)?
如果是这样,那么您的App.vue
就可以了。在您的“用户列表组件”中,也可以使用mapGetters
来获取值(注意它应该在computed 中)。问题是您应该先“等待”setUsers
操作完成,以便组件中的getUsers
可以有价值。
解决此问题的一种简单方法是使用Conditional Rendering,并且仅在定义getUsers
时呈现组件。可能您可以将v-if
添加到“用户列表组件”的父组件中,并且仅在v-if="getUsers"
为真时加载它。然后你的挂载逻辑也可以正常工作(因为数据已经存在)。
【讨论】:
【参考方案3】:如果您从 API 获取数据,那么最好在尚未渲染 DOM 的 created 内部调度操作,但您仍然可以使用“this”而不是 mount。如果您正在使用 Vuex 模块,以下是一个示例:
created()
this.fetchUsers();
,
methods:
async fetchUsers()
await this.$store.dispatch('user/setUsers');
,
,
computed:
usersGetters()
// getters here
,
,
【讨论】:
以上是关于如何在带有 vuex 的 vue 生命周期钩子中使用 async/await?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Vuex 操作完成之前阻止 Vue 生命周期继续进行?