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

当用户尝试直接导航加载组件 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在加载我的组件之前,如何让我的组件等待加载?


慕容森
浏览 255回答 3
3回答

慕村9548890

这样做的方法是存储状态值。例如,如果您的商店依赖于单个 API,您将执行以下操作。但是,对于多个 API,最好单独存储每个 api 加载状态,或者为每个 API 使用一个专用对象。通常你可以拥有 4 种状态,我更喜欢在全局可访问模块中拥有它们:// enums.jsexport default {&nbsp; INIT: 0,&nbsp; LOADING: 1,&nbsp; ERROR: 2,&nbsp; LOADED: 3};然后,您可以将变量存储在 vuex 状态中,其中 apiState 使用INIT. 您也可以使用 初始化数组[],但这不是必需的。import ENUM from "@/enums";// store.jsexport default new Vuex.Store({&nbsp; state: {&nbsp; &nbsp; apiState: ENUM.INIT,&nbsp; &nbsp; accounts: [],&nbsp; &nbsp; // ...other state&nbsp; },&nbsp; mutations: {&nbsp; &nbsp; updateAccounts (state, accounts) {&nbsp; &nbsp; &nbsp; state.accounts = accounts;&nbsp; &nbsp; &nbsp; state.apiState = ENUM.LOADED;&nbsp; &nbsp; },&nbsp; &nbsp; setApiState (state, apiState) {&nbsp; &nbsp; &nbsp; state.apiState = apiState;&nbsp; &nbsp; },&nbsp; },&nbsp; actions: {&nbsp; &nbsp; loadAccounts ({commit) {&nbsp; &nbsp; &nbsp; commit('setApiState', ENUM.ERROR);&nbsp; &nbsp; &nbsp; somFetchInterface()&nbsp; &nbsp; &nbsp; &nbsp; .then(data=>commit('updateAccounts', data))&nbsp; &nbsp; &nbsp; &nbsp; .catch(err=>commit('setApiState', ENUM.ERROR))&nbsp; &nbsp; }&nbsp; }});然后,通过添加一些computeds,您可以切换显示哪个组件。这显示了使用状态的好处,因为您可以轻松识别错误状态,并在状态未准备好时显示加载动画。<template>&nbsp; <ChildComponent v-if="apiStateLoaded"/>&nbsp; <Loader v-if="apiStateLoading"/>&nbsp; <Error v-if="apiStateError"/></template><script>import ENUM from "@/enums";export default {&nbsp; computed: {&nbsp; &nbsp; ...mapState({&nbsp; &nbsp; &nbsp; apiState: state=> state.apiState&nbsp; &nbsp; }),&nbsp; &nbsp; apiStateLoaded() {&nbsp; &nbsp; &nbsp; return this.apiState === ENUM.LOADED;&nbsp; &nbsp; },&nbsp; &nbsp; apiStateLoading() {&nbsp; &nbsp; &nbsp; return this.apiState === ENUM.LOADING || this.apiState === ENUM.INIT;&nbsp; &nbsp; },&nbsp; &nbsp; apiStateError() {&nbsp; &nbsp; &nbsp; return this.apiState === ENUM.ERROR;&nbsp; &nbsp; },&nbsp; })}</script>或者,如果您只是asyncListValues使用空数组在 store 中初始化[],则可以避免期望数组的错误。

ibeautiful

由于您vue-router在问题中提到过,您可以使用beforeRouteEnterwhich 来推迟组件的渲染。例如,如果您有一条名为“photo”的路线:import Photo from "../page/Photo.vue";new VueRouter({&nbsp; mode: "history",&nbsp; routes: [&nbsp; &nbsp; { name: "home", path: "/", component: Home },&nbsp; &nbsp; { name: "photo", path: "/photo", component: Photo }&nbsp; ]});你可以这样使用beforeRouteEnter:<template>&nbsp; <div>&nbsp; &nbsp; Photo rendered here&nbsp; </div></template><script>export default {&nbsp; beforeRouteEnter: async function(to, from, next) {&nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; await this.$store.dispatch("longRuningHttpCall");&nbsp; &nbsp; &nbsp; next();&nbsp; &nbsp; } catch(exception) {&nbsp; &nbsp; &nbsp; next(exception);&nbsp; &nbsp; }&nbsp; }}</script>它的作用是,等待操作完成,根据需要更新您的状态,然后调用next()将告诉路由器继续该过程(在 中渲染组件<router-view></router-view>)。告诉我您是否需要 ES6-less 示例(例如,如果您不使用此语法)。您可以查看此页面上的官方文档beforeRouteEnter,您还会发现您也可以使用beforeEnter.

侃侃尔雅

一种方法是将您的组件拆分为两个不同的组件。一旦数据准备好,您的新父组件可以处理获取数据并呈现子组件。父组件.vue<template>&nbsp; <child-component v-if="asyncListValues && asyncListValues.length" :asyncListValues="asyncListValues"/>&nbsp; <div v-else>Placeholder</div></template><script>export default {&nbsp; computed: {&nbsp; &nbsp; ...mapState({&nbsp; &nbsp; &nbsp; asyncListValues: state => state.asyncListValues&nbsp; &nbsp; })&nbsp; }}</script>子组件.vueexport default {&nbsp; props: ["asyncListValues"],&nbsp; mounted () {&nbsp; &nbsp; this.asyncListValues.forEach((val) => {&nbsp;&nbsp; &nbsp; &nbsp; // do stuff&nbsp; &nbsp; });&nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript