可自定义设置以下属性:
-
是否为加载中状态(spinning),类型:boolean,默认 true
-
组件大小(size),类型:string,默认 'default',可选:small | default | large
-
描述文案(tip),类型:string | slot,默认 ''
-
加载指示符(indicator),类型:string,默认 'dot',可选:dot | circle
效果如下图:
①创建加载中组件Spin.vue:
<script setup lang="ts">
interface Props {
spinning?: boolean // 是否为加载中状态
size?: string // 组件大小,可选small default large
tip?: string // 描述文案 string | slot
indicator?: string // 加载指示符 string
}
withDefaults(defineProps<Props>(), {
spinning: true,
size: 'default',
tip: '',
indicator: 'dot' // 可选 dot | circle
})
</script>
<template>
<div :class="`m-spin-wrap ${size}`">
<div class="m-spin" v-show="spinning">
<div class="m-spin-box">
<div class="m-spin-dot" v-if="indicator==='dot'">
<span class="u-dot-item"></span>
<span class="u-dot-item"></span>
<span class="u-dot-item"></span>
<span class="u-dot-item"></span>
</div>
<div v-if="indicator==='circle'" class="u-spin-circle"></div>
<p class="u-tip" v-show="tip">{
{ tip }}</p>
</div>
</div>
<div :class="['m-spin-content', {'m-spin-mask': spinning}]">
<slot></slot>
</div>
</div>
</template>
<style lang="less" scoped>
.m-spin-wrap {
position: relative;
height: 100%;
width: 100%;
}
.m-spin {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
z-index: 9;
.m-spin-box {
text-align: center;
.m-spin-dot {
position: relative;
display: inline-block;
transform: rotate(45deg);
-ms-transform: rotate(45deg); /* Internet Explorer */
-moz-transform: rotate(45deg); /* Firefox */
-webkit-transform: rotate(45deg); /* Safari 和 Chrome */
-o-transform: rotate(45deg); /* Opera */
animation: loadingDot 1.2s infinite linear;
-webkit-animation: loadingDot 1.2s infinite linear;
@keyframes loadingDot {
100% {transform: rotate(405deg);} // to {transform: rotate(405deg);}
}
.u-dot-item { // 单个圆点样式
position: absolute;
background: @themeColor;
border-radius: 50%;
opacity: .3;
animation: spinMove 1s linear infinite alternate;
-webkit-animation: spinMove 1s linear infinite alternate;
@keyframes spinMove {
100% {opacity: 1;}
}
}
.u-dot-item:first-child {
top: 0;
left: 0;
}
.u-dot-item:nth-child(2) {
top: 0;
right: 0;
animation-delay: .4s;
-webkit-animation-delay: .4s;
}
.u-dot-item:nth-child(3) {
bottom: 0;
right: 0;
animation-delay: .8s;
-webkit-animation-delay: .8s;
}
.u-dot-item:last-child {
bottom: 0;
left: 0;
animation-delay: 1.2s;
-webkit-animation-delay: 1.2s;
}
}
.u-spin-circle {
display: inline-block;
border-radius: 50%;
border-style: solid;
border-color: @themeColor;
border-top-color: transparent; // 隐藏1/4圆
animation: loadingCircle 1s infinite linear;
-webkit-animation: loadingCircle 1s infinite linear;
}
@keyframes loadingCircle {
100% {
transform: rotate(360deg);
}
}
.u-tip {
color: @themeColor;
text-align: center;
}
}
}
.large {
.m-spin .m-spin-box {
.m-spin-dot {
width: 36px;
height: 36px;
.u-dot-item {
width: 13px;
height: 13px;
}
}
.u-spin-circle {
width: 40px;
height: 40px;
border-width: 5px;
}
.u-tip {
font-size: 16px;
font-weight: 500;
line-height: 20px;
padding-top: 10px;
}
}
}
.default {
.m-spin .m-spin-box {
.m-spin-dot {
width: 28px;
height: 28px;
.u-dot-item {
width: 10px;
height: 10px;
}
}
.u-spin-circle {
width: 32px;
height: 32px;
border-width: 4px;
}
.u-tip {
font-size: 14px;
font-weight: 500;
line-height: 18px;
padding-top: 6px;
}
}
}
.small {
.m-spin .m-spin-box {
.m-spin-dot {
width: 20px;
height: 20px;
.u-dot-item {
width: 7px;
height: 7px;
}
}
.u-spin-circle {
width: 24px;
height: 24px;
border-width: 3px;
}
.u-tip {
font-size: 14px;
font-weight: 400;
line-height: 16px;
padding-top: 4px;
}
}
}
.m-spin-content {
transition: opacity .3s;
}
.m-spin-mask {
user-select: none;
pointer-events: none;
opacity: 0.4;
}
</style>
②在要使用的页面引入:
<script setup lang="ts">
import { Spin } from './Spin.vue'
import { ref } from 'vue'
const tip = ref('加载中...')
const spinning = ref(true)
</script>
<template>
<div>
<h2 class="mb10">Spin 加载中基本使用</h2>
<Spin style="width: 800px;" :tip="tip" :spinning="spinning">
<p class="spin-content">当 spinning 为 false 时,不显示 loading 状态;当 spinning 为 true 时,延迟`delay`ms时间后,显示 loading 效果;如果 spinning 状态在 `delay` 时间内结束,则不显示 loading 状态;如果不设置 tip 描述文案时,则只有 loading 效果水平垂直居中;如果设置了 tip 描述文案,则 loading 效果和 tip 描述文案一起水平垂直居中。</p>
</Spin>
<h2 class="mt30 mb10">圆形加载指示符 (indicator: circle)</h2>
<Spin style="width: 800px;" :tip="tip" :spinning="spinning" indicator="circle">
<p class="spin-content">当 spinning 为 false 时,不显示 loading 状态;当 spinning 为 true 时,延迟`delay`ms时间后,显示 loading 效果;如果 spinning 状态在 `delay` 时间内结束,则不显示 loading 状态;如果不设置 tip 描述文案时,则只有 loading 效果水平垂直居中;如果设置了 tip 描述文案,则 loading 效果和 tip 描述文案一起水平垂直居中。</p>
</Spin>
<h2 class="mt30 mb10">各种大小</h2>
<Spin :tip="tip" class="u-spin" :spinning="spinning" size="small" />
<Spin :tip="tip" class="u-spin" :spinning="spinning" size="default" />
<Spin :tip="tip" class="u-spin" :spinning="spinning" size="large" />
<Spin :tip="tip" class="u-spin" :spinning="spinning" size="small" indicator="circle" />
<Spin :tip="tip" class="u-spin" :spinning="spinning" size="default" indicator="circle" />
<Spin :tip="tip" class="u-spin" :spinning="spinning" size="large" indicator="circle" />
<h3>Loading state: <Switch v-model:checked="spinning" /></h3>
<h2 class="mt30 mb10">Ant Design Vue 加载中</h2>
<a-spin class="border-box" :tip="tip" size="default" :spinning="spinning">
<p class="spin-content">当 spinning 为 false 时,不显示 loading 状态;当 spinning 为 true 时,延迟`delay`ms时间后,显示 loading 效果;如果 spinning 状态在 `delay` 时间内结束,则不显示 loading 状态;如果不设置 tip 描述文案时,则只有 loading 效果水平垂直居中;如果设置了 tip 描述文案,则 loading 效果和 tip 描述文案一起水平垂直居中。</p>
</a-spin>
</div>
</template>
<style lang="less" scoped>
.spin-content {
display: inline-block;
border: 1px solid #91d5ff;
background-color: #e6f7ff;
padding: 30px;
}
.u-spin {
display: inline-block;
width: 100px;
height: 100px;
}
.border-box {
:deep(*) {
box-sizing: border-box;
}
}
</style>