Suspense组件有两个template,fallback
表示渲染请求期间的内容,default
表示渲染请求完成后的内容:
<Suspense>
<template #default>
<请求完成后内容 />
</template>
<template #fallback>
<h1>Loading !...</h1>
</template>
</Suspense>
异步组件
配合 vue3 中 defineAsyncComponent 来加载异步组件
defineAsyncComponent
接受一个函数作为参数,返回为import一个组件对象
通过v-if
切换组件的加载过程
<template>
<button @click="loadAsyncComponent">点击加载异步组件</button>
<Suspense v-if="loadAsync">
<template #default>
<AsyncComponent></AsyncComponent>
</template>
<template #fallback>
<div class="loading"></div>
</template>
</Suspense>
</template>
<script>
import { defineAsyncComponent } from "vue";
export default {
name: "App",
data() {
return {
loadAsync: false
};
},
components: {
HelloWorld,
AsyncComponent: defineAsyncComponent(() => {
return import("./components/async-component.vue");
})
},
methods: {
loadAsyncComponent() {
this.loadAsync = true;
}
}
};
</script>
<style lang="scss">
#app {
width: 800px;
height: 600px;
padding: 20px;
margin: 0 auto;
border: 1px solid #eeeeee;
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
position: relative;
}
button {
padding: 12px 12px;
background-color: #1890ff;
outline: none;
border: none;
border-radius: 4px;
color: #fff;
cursor: pointer;
}
.loading {
position: absolute;
width: 36px;
height: 36px;
top: 50%;
left: 50%;
margin: -18px 0 0 -18px;
background-image: url("./assets/images/Loading.png");
background-size: 100%;
animation: rotate 1.4s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
</style>
实现数据加载中的效果
在setup()里面需要返回一个promise,使用Suspense组件引该组件时,请求完成之前会一起显示loading效果
<template>
<img :src="result && result.message">
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
async setup() {
const rawData = await axios.get('https://dog.ceo/api/breeds/image')
return {
result: rawData.data
}
}
})
</script>
实现路由加载效果
在路由完全加载前默认使用fallback里面的内容
<router-link to="/home">Home</router-link>|
<router-link to="/about">About</router-link>
<Suspense>
<template #default>
<router-view />
</template>
<template #fallback>
<div class="loading"></div>
</template>
</Suspense>