Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

589
Visualizações
Vue 3: Wait until parent is done with data fetching to fetch child data and show loader

I'm looking for a reusable way to display a full page loader (Sidebar always visible but the loader should cover the content part of the page) till all necessary api fetches has been done.

I've got a parent component LaunchDetails wrapped in a PageLoader component

LaunchDetails.vue

<template>
  <PageLoader>
    <router-link :to="{ name: 'launches' }"> Back to launches </router-link>
    <h1>{{ name }}</h1>

    <section>
      <TabMenu :links="menuLinks" />
    </section>

    <section>
      <router-view />
    </section>
  </PageLoader>
</template>

<script>
import TabMenu from "@/components/general/TabMenu";

export default {
  data() {
    return {
      menuLinks: [
        { to: { name: "launchOverview" }, display_name: "Overview" },
        { to: { name: "launchRocket" }, display_name: "Rocket" },
      ],
    };
  },
  components: {
    TabMenu,
  },
  created() {
    this.$store.dispatch("launches/fetchLaunch", this.$route.params.launch_id);
  },
  computed: {
    name() {
      return this.$store.getters["launches/name"];
    },
  },
};
</script>

PageLoader.vue

<template>
  <Spinner v-if="isLoading" full size="medium" />
  <slot v-else></slot>
</template>

<script>
import Spinner from "@/components/general/Spinner.vue";

export default {
  components: {
    Spinner,
  },
  computed: {
    isLoading() {
      return this.$store.getters["loader/isLoading"];
    },
  },
};
</script>

The LaunchDetails template has another router-view. In these child pages new fetch requests are made based on data from the LaunchDetails requests.

RocketDetails.vue

<template>
  <PageLoader>
    <h2>Launch rocket details</h2>

    <RocketCard v-if="rocket" :rocket="rocket" />
  </PageLoader>
</template>

<script>
import LaunchService from "@/services/LaunchService";
import RocketCard from "@/components/rocket/RocketCard.vue";

export default {
  components: {
    RocketCard,
  },
  mounted() {
    this.loadRocket();
  },
  data() {
    return {
      rocket: null,
    };
  },
  methods: {
    async loadRocket() {
      const rocket_id = this.$store.getters["launches/getRocketId"];

      if (rocket_id) {
        const response = await LaunchService.getRocket(rocket_id);
        this.rocket = response.data;
      }
    },
  },
};
</script>

What I need is a way to fetch data in the parent component (LaunchDetails). If this data is stored in the vuex store, the child component (LaunchRocket) is getting the necessary store data and executes the fetch requests. While this is done I would like to have a full page loader or a full page loader while the parent component is loading and a loader containing the nested canvas.

At this point the vuex store is keeping track of an isLoading property, handled with axios interceptors.

All code is visible in this sandbox

(Note: In this example I could get the rocket_id from the url but this will not be the case in my project so I'm really looking for a way to get this data from the vuex store)

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Im introduce your savior Suspense, this feature has been added in vue v3 but still is an experimental feature. Basically how its work you create one suspense in parent component and you can show a loading when all component in any depth of your application is resolved. Note that your components should be an async component means that it should either lazily loaded or made your setup function (composition api) an async function so it will return an async component, with this way you can fetch you data in child component and in parent show a fallback if necessary.

More info: https://v3.vuejs.org/guide/migration/suspense.html#introduction

over 4 years ago · Santiago Trujillo Relatório

0

You could use Events:

var Child = Vue.component('child', {
  data() {
    return {
      isLoading: true
    }
  },
  template: `<div>
    <span v-if="isLoading">Loading &hellip;</span>
    <span v-else>Child</span>
  </div>`,
  created() {
    this.$parent.$on('loaded', this.setLoaded);
  },
  methods: {
    setLoaded() {
      this.isLoading = false
    }
  }
});

var Parent = Vue.component('parent', {
  components: { Child },
  data() {
    return {
      isLoading: true
    }
  },
  template: `<div>
    Parent
    <Child />
  </div>`,
  mounted() {
    let request1 = new Promise((resolve, reject) => {
      setTimeout(resolve, 1000);
    });
    let request2 = new Promise((resolve, reject) => {
      setTimeout(resolve, 2000);
    });
    Promise.all([ request1, request2 ]).then(() => this.$emit('loaded'))
  }
});

new Vue({
  components: { Parent },
  el: '#app',
  template: `<Parent />`
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

This may be considered an anti-pattern since it couples the parent with the child and events are considered to be sent the other way round. If you don't want to use events for that, a watched property works just fine, too. The non-parent-child event emitting was removed in Vue 3 but can be implemented using external libraries.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda