如何在vue生命周期钩子中使用vuex使用async/await?

问题描述 投票:0回答:3

当我在 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
文件?

vue.js vuejs2 vue-component vuex
3个回答
18
投票

您在组件中正确使用了异步等待。重要的是要了解

async await
不会推迟组件的执行,并且您的组件仍然会渲染并经历不同的生命周期挂钩,例如
mounted

async await
所做的是推迟当前上下文的执行,如果您在函数内使用它,
await
之后的代码将在承诺解析后发生,在您的情况下,您正在使用它位于
created
生命周期钩子中,这意味着
mounted
生命周期钩子内的代码是一个函数,将在等待后得到解析。

因此,您要做的就是确保仅在收到数据时渲染组件。

具体操作方法如下:

  1. 如果该组件是父组件的子组件,则可以使用
    v-if
    ,然后当数据到来时将 data 设置为 true,如下所示:
<SomeComponent v-if="hasData" />
data() {
  return {
    hasData: false,
  }
}

async mounted() {
  const users = await fetchUsers()
  this.hasData = true;
}
  1. 如果组件不是父组件的子组件,您可以使用
    watcher
    让您知道组件何时渲染。使用
    watch
    时你要小心,因为每次发生变化都会发生这种情况。

一个简单的经验法则是对不经常更改的变量使用 watch,如果您获取的数据大部分是只读的,您可以使用这些数据,如果不是,您可以向 Vuex 添加一个属性,例如

loadingUsers
.

以下是如何执行此操作的示例:

<SomeComponent v-if="hasData" />
data: {
  return {
    hasData: false,
  }
},
 
computed: {
  isLoading() {
    return this.$store.state.app.users;
  }
},
  
watch: {
  isLoading(isLoading) {
    if (!isLoading) {
      this.hasData = true;
    }
  }
}

0
投票

如果您要从 API 获取数据,那么最好在 DOM 尚未呈现的地方分派 create 中的操作,但您仍然可以使用“this”而不是 Mounted。如果您使用 Vuex 模块,这里是一个示例:

created() {
  this.fetchUsers();
},
methods: {
  async fetchUsers() {
    await this.$store.dispatch('user/setUsers');
  },
},
computed: {
  usersGetters() {
    // getters here
  },
},

0
投票

问题:您是否希望每次加载应用程序时都运行

await this.setUsers();
(无论显示哪个页面/组件)?

如果是这样,那么你的

App.vue
就可以了。在“用户列表组件”中,也可以使用
mapGetters
来获取值(注意它应该在 compulated 中)。问题是您应该先“等待”
setUsers
操作完成,这样组件中的
getUsers
才能有价值。

解决此问题的一个简单方法是使用条件渲染,并且仅在定义

getUsers
时渲染组件。也许您可以将
v-if
添加到“用户列表组件”的父组件中,并且仅在
v-if="getUsers"
为 true 时加载它。那么您安装的逻辑也可以正常工作(因为数据已经存在)。

© www.soinside.com 2019 - 2024. All rights reserved.