如何在带有 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 生命周期继续进行?

Vuex this.$store 在“挂载”生命周期钩子中未定义

Java面试题-前端Vue

Java面试题-前端Vue

Java面试题-前端Vue

vue生命周期钩子函数如何第二次打开不请求接口