I read this part of documentation: https://vuejs.org/guide/built-ins/suspense.html#combining-with-other-components
I have in my menu 2 links: "Home" and "Tools". If I land on my root page, that is to say the "Home" route, then I go to the "Tools" route, the "Loading..." message doesn't show. I have to wait 2 seconds, though, meaning the async component waits to be loaded to be displayed. If I go to the "Tools" route directly, I see the message. I don't understand what I did wrong because I want the "Loading..." message to show when I load this async component, even if I come from another route.
In my App.vue
I have this:
<script setup>
import Connexion from '@/components/Connexion.vue'
import { ref } from 'vue'
const drawer = ref(null);
</script>
<template>
<v-app>
<v-navigation-drawer
expand-on-hover
rail>
<Suspense>
<Connexion />
<template #fallback>
Chargement...
</template>
</Suspense>
<v-divider></v-divider>
<v-list density="compact" nav>
<v-list-item prepend-icon="mdi-home" title="Home" value="home" @click="$router.push('/')"></v-list-item>
<v-list-item prepend-icon="mdi-account-multiple" title="Tools" value="tools" @click="$router.push('/tools')"></v-list-item>
</v-list>
</v-navigation-drawer>
<v-app-bar>
<v-toolbar-title>My app</v-toolbar-title>
</v-app-bar>
<v-main fluid fill-width>
XXX
<v-container
fluid
>
<router-view v-slot="{ Component }">
<template v-if="Component">
<Transition mode="out-in">
<keep-alive>
<Suspense>
<component :is="Component" />
<template #fallback>
Loading...
</template>
</Suspense>
</keep-alive>
</Transition>
</template>
</router-view>
</v-container>
</v-main>
</v-app>
</template>
<style>
/* we will explain what these classes do next! */
.v-enter-active,
.v-leave-active {
transition: opacity 0.2s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
</style>
And here is the Tools.vue
component:
<script>
import { defineComponent } from "vue";
export default defineComponent({
async setup() {
const apiUrl = import.meta.env.VITE_APP_API_URL;
console.log("loading...")
const demandes = await fetch(`${apiUrl}/tools`)
.then((r) => r.json())
.catch((e) => {
console.log(e);
return [];
});
await new Promise(r => setTimeout(r, 2000));
console.log("LOADED!")
return {
demandes,
}
}
})
</script>
<template>
<div>
<h1>Tools</h1>
<ul>
<li
v-for="tool in tools"
:key="`tool-${tool.id}`"
>
{{ tool }}
</li>
</ul>
</div>
</template>
If it has any interest, here is my router
file:
import { createRouter, createWebHistory } from 'vue-router';
import { nextTick } from 'vue';
const routes = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: {
title: 'Home',
},
},
{
path: '/tools',
name: 'Tools',
component: () => import('@/views/Tools.vue'),
meta: {
title: 'Tools',
},
},
];
const router = createRouter({
base: import.meta.env.VITE_APP_PUBLICPATH,
history: createWebHistory(import.meta.env.VITE_APP_BASE_URL),
routes,
});
const DEFAULT_TITLE = import.meta.env.VITE_APP_TITLE;
router.afterEach((to) => {
nextTick(() => {
document.title = to.meta.title ? `${DEFAULT_TITLE} - ${to.meta.title}` : DEFAULT_TITLE;
});
});
export default router;
And the Home.vue
:
<script setup>
</script>
<template>
<h1>Home</h1>
</template>
<style scoped>
</style>