JSFiddle - React, Tailwind, and code Playground
by skirtle
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.global.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue-router.global.js"></script>
<div id="app">
<router-link to="/">Home</router-link> -
<router-link to="/other">About</router-link>
<div class="main" :class="{ loading }">
<router-view v-slot="{ Component }">
<template v-if="Component">
<transition mode="out-in">
<keep-alive>
<suspense
@pending="loading = true"
@resolve="loading = false"
>
<component :is="Component"></component>
<template #fallback>
<div>
Loading...
</div>
</template>
</suspense>
</keep-alive>
</transition>
</template>
</router-view>
</div>
</div>
CSS
#app, .main {
padding: 20px;
margin: 20px;
border: 1px solid red;
}
.v-enter-from, .v-leave-to {
opacity: 0;
}
.v-enter-active, .v-leave-active {
transition: opacity 500ms;
}
.loading {
position: relative;
}
.loading::after {
background: #ccc;
bottom: 0;
content: '';
left: 0;
opacity: 0.5;
position: absolute;
right: 0;
top: 0;
}
JavaScript
const resolveComponent = name => {
return new Promise(resolve => {
setTimeout(() => {
resolve({
template: `<div>${name} - created {{ time }} seconds ago</div>`,
data () {
return {
time: 0
}
},
created () {
setInterval(() => {
this.time++
}, 1000)
}
})
}, 2000)
})
}
const app = Vue.createApp({
data () {
return {
loading: false
}
}
})
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: [
{
path: '/',
// component: () => resolveComponent('Home'),
component: {
render: () => Vue.h(Vue.resolveComponent('Home')),
components: {
Home: Vue.defineAsyncComponent(() => resolveComponent('Home'))
}
}
}, {
path: '/other',
// component: () => resolveComponent('About'),
component: {
render: () => Vue.h(Vue.resolveComponent('About')),
components: {
About: Vue.defineAsyncComponent(() => resolveComponent('About'))
}
}
}
]
})
app.use(router)
app.mount('#app')