为了账号安全,请及时绑定邮箱和手机立即绑定

在加载组件之前等待 VueX 值加载

在加载组件之前等待 VueX 值加载

慕容森 2021-06-29 07:59:52
当用户尝试直接导航加载组件 url 时,我的 vuex 操作中会进行一个 http 调用,一旦它解析,它将在我的状态中定义一个值。在解析 http 调用并定义状态值之前,我不想加载我的组件。例如,在我的组件中export default {  computed: {    ...mapState({      // ** this value needs to load before component mounted() runs **      asyncListValues: state => state.asyncListValues    })  },  mounted () {    // ** I need asyncListValues to be defined before this runs **    this.asyncListValues.forEach((val) => {       // do stuff    });  }}asyncListValues在加载我的组件之前,如何让我的组件等待加载?
查看完整描述

3 回答

?
慕村9548890

TA贡献1884条经验 获得超4个赞

这样做的方法是存储状态值。


例如,如果您的商店依赖于单个 API,您将执行以下操作。但是,对于多个 API,最好单独存储每个 api 加载状态,或者为每个 API 使用一个专用对象。


通常你可以拥有 4 种状态,我更喜欢在全局可访问模块中拥有它们:


// enums.js

export default {

  INIT: 0,

  LOADING: 1,

  ERROR: 2,

  LOADED: 3

};

然后,您可以将变量存储在 vuex 状态中,其中 apiState 使用INIT. 您也可以使用 初始化数组[],但这不是必需的。


import ENUM from "@/enums";

// store.js

export default new Vuex.Store({

  state: {

    apiState: ENUM.INIT,

    accounts: [],

    // ...other state

  },

  mutations: {

    updateAccounts (state, accounts) {

      state.accounts = accounts;

      state.apiState = ENUM.LOADED;

    },

    setApiState (state, apiState) {

      state.apiState = apiState;

    },

  },

  actions: {

    loadAccounts ({commit) {

      commit('setApiState', ENUM.ERROR);

      somFetchInterface()

        .then(data=>commit('updateAccounts', data))

        .catch(err=>commit('setApiState', ENUM.ERROR))

    }

  }

});

然后,通过添加一些computeds,您可以切换显示哪个组件。这显示了使用状态的好处,因为您可以轻松识别错误状态,并在状态未准备好时显示加载动画。


<template>

  <ChildComponent v-if="apiStateLoaded"/>

  <Loader v-if="apiStateLoading"/>

  <Error v-if="apiStateError"/>

</template>

<script>

import ENUM from "@/enums";

export default {

  computed: {

    ...mapState({

      apiState: state=> state.apiState

    }),

    apiStateLoaded() {

      return this.apiState === ENUM.LOADED;

    },

    apiStateLoading() {

      return this.apiState === ENUM.LOADING || this.apiState === ENUM.INIT;

    },

    apiStateError() {

      return this.apiState === ENUM.ERROR;

    },

  })

}

</script>

或者,如果您只是asyncListValues使用空数组在 store 中初始化[],则可以避免期望数组的错误。


查看完整回答
反对 回复 2021-07-01
?
ibeautiful

TA贡献1993条经验 获得超5个赞

由于您vue-router在问题中提到过,您可以使用beforeRouteEnterwhich 来推迟组件的渲染。


例如,如果您有一条名为“photo”的路线:


import Photo from "../page/Photo.vue";


new VueRouter({

  mode: "history",

  routes: [

    { name: "home", path: "/", component: Home },

    { name: "photo", path: "/photo", component: Photo }

  ]

});

你可以这样使用beforeRouteEnter:


<template>

  <div>

    Photo rendered here

  </div>

</template>

<script>

export default {

  beforeRouteEnter: async function(to, from, next) {

    try {

      await this.$store.dispatch("longRuningHttpCall");


      next();

    } catch(exception) {

      next(exception);

    }

  }

}

</script>

它的作用是,等待操作完成,根据需要更新您的状态,然后调用next()将告诉路由器继续该过程(在 中渲染组件<router-view></router-view>)。


告诉我您是否需要 ES6-less 示例(例如,如果您不使用此语法)。


您可以查看此页面上的官方文档beforeRouteEnter,您还会发现您也可以使用beforeEnter.


查看完整回答
反对 回复 2021-07-01
?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

一种方法是将您的组件拆分为两个不同的组件。一旦数据准备好,您的新父组件可以处理获取数据并呈现子组件。


父组件.vue


<template>

  <child-component v-if="asyncListValues && asyncListValues.length" :asyncListValues="asyncListValues"/>

  <div v-else>Placeholder</div>

</template>

<script>

export default {

  computed: {

    ...mapState({

      asyncListValues: state => state.asyncListValues

    })

  }

}

</script>

子组件.vue


export default {

  props: ["asyncListValues"],

  mounted () {

    this.asyncListValues.forEach((val) => { 

      // do stuff

    });

  }

}


查看完整回答
反对 回复 2021-07-01
  • 3 回答
  • 0 关注
  • 253 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信