确保在渲染组件之前加载 Vuex 状态

Dej*_*n.S 9 vue.js vue-component vuex

我有一个add-user.vue组件。这是我添加新用户和编辑现有用户的模板。所以在页面加载时,我检查路由是否有id,如果有,我从状态数组加载用户以进行编辑。我的问题是user未定义,因为状态数组users为空。如何确保我的用户对象不是未定义的。它有时会加载,但在刷新时不会加载。我以为我把它盖好了,但没有。这是我的设置。我在这里缺少什么?

店铺

state: {
  users: []
},

getters: {
  users: state =>
    _.keyBy(state.users.filter(user => user.deleted === false), 'id')
},

actions: {
  fetchUsers({
    commit
  }) {
    axios
      .get('http://localhost:3000/users')
      .then(response => {
        commit('setUsers', response.data);
      })
      .catch(error => {
        console.log('error:', error);
      });
  }
}
Run Code Online (Sandbox Code Playgroud)

在我的add-user.vue组件中,我在data() computed:{}created()

data() {
  return {
    user: {
      id: undefined,
      name: undefined,
      gender: undefined
    }
  };
},

computed: {
  ...mapGetters(['users'])
},

created() {
  if (this.$route.params.userId === undefined) {
    this.user.id = uuid();
    ...
  } else {
    this.user = this.users[this.$route.params.userId];
  }
}
Run Code Online (Sandbox Code Playgroud)

模板

<template>
  <div class="add-user" v-if="user"></div>
</template>
Run Code Online (Sandbox Code Playgroud)

我的User.vue我有以下设置,我在那里初始化用户的获取created()

<template>
  <main class="main">
    <AddUser/>
    <UserList/>
  </main>
</template>

<script>
import AddUser from '@/components/add-user.vue';
import UserList from '@/components/user-list.vue';

export default {
    name: 'User',

    components: {
        AddUser,
        UserList
    },

    created() {
        this.$store.dispatch('fetchUsers');
    }
};
</script>
Run Code Online (Sandbox Code Playgroud)

我试过这个。在我的编辑器中保存时,它可以工作但不能刷新。将dispatch().then()在之前运行mutation的用户不设置。

created() {
  if (this.$route.params.userId === undefined) {
    this.user.id = uuid();
    ...
  } else {
    if (this.users.length > 0) {
                this.user = this.users[this.$route.params.userId];
            } else {
                this.$store.dispatch('fetchUsers').then(() => {
                    this.user = this.users[this.$route.params.userId];
                });
            }
  }
}
Run Code Online (Sandbox Code Playgroud)

小智 10

我会使用beforeRouteEnterinUser.vue以便在加载数据之前不会初始化组件。(假设您正在使用vue-router

beforeRouteEnter (to, from, next) {
    if (store.state.users.length === 0) {
        store.dispatch(fetchUsers)
        .then(next);
    }
},
Run Code Online (Sandbox Code Playgroud)

您需要这样做, import store from 'path/to/your/store' 因为this.$store在组件初始化之前不可用。


adn*_*leb 5

虽然这解决了,但我会为未来的人回答。您可以dispatch像 Shu 建议的那样预先发布,或者您仍然可以在同一个组件mounted挂钩上调度,但使用一些状态变量来跟踪进度:

data:{
    ...
    loading:false,
    ...
},
...
mounted(){
this.loading = true,
this.$store
  .dispatch('fetchUsers')
  .finally(() => (this.loading=false));
}
Run Code Online (Sandbox Code Playgroud)

然后在您的模板中使用此loading状态变量来呈现页面或呈现一些微调器或进度条:

<template>
    <div class='main' v-if="!loading">
        ...all old template goes her
    </div>
    <div class="overlay" v-else>
        Loading...
    </div>
</template>

<style scoped>
    .overlay {
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 10;
      color: #FFFFFF;
    }
</style>
Run Code Online (Sandbox Code Playgroud)


Dej*_*n.S 1

对于这个特殊情况,它只是来回访问同一个 vue 实例。通过添加解决了它:key="some-unique-key",所以它看起来像这样。

<template>
  <main class="main">

    <AddUser :key="$route.params.userId"/>

    <UserList/>

  </main>
</template>
Run Code Online (Sandbox Code Playgroud)