Vue3加载中(Spin)

Vue2加载中(Spin)

可自定义设置以下属性:

  • 是否为加载中状态(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>

猜你喜欢

转载自blog.csdn.net/Dandrose/article/details/129989730
今日推荐