vue3 封装loading插件

745 阅读1分钟

1. 在components中新建loading文件夹

image.png

index.vue代码:

<template>
  <div v-if="isShow" class="loading_container">
    <div class="loader">
      <div class="outer"></div>
      <div class="middle"></div>
      <div class="inner"></div>
      <div class="loading">加载中<span class="load"></span></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
const isShow = ref<boolean>(false);
const show = () => (isShow.value = true);
const hide = () => (isShow.value = false);

defineExpose({
  show,
  hide,
  isShow,
});
</script>

<style scoped lang="less">
.loading_container {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
}
.loader {
  position: relative;
  .loading {
    margin-top: 6em;
    color: #3cefff;
    letter-spacing: 5px;
    .load {
      height: 2px;
      width: 2px;
      display: inline-block;
      /*box-shadow: 2px 0 0 white ,7px 0 0 white, 12px 0 0 white;*/
      animation: change 2.4s infinite steps(1, start);
    }
    @keyframes change {
      25% {
        box-shadow: 2px 0 0 #3cefff;
      }
      50% {
        box-shadow: 2px 0 0 #3cefff, 7px 0 0 #3cefff;
      }
      75% {
        box-shadow: 2px 0 0 #3cefff, 7px 0 0 #3cefff, 12px 0 0 #3cefff;
      }
    }
  }
}

.outer,
.middle,
.inner {
  border: 3px solid transparent;
  border-top-color: #3cefff;
  border-right-color: #3cefff;
  border-radius: 50%;
  position: absolute;
  top: 50%;
  left: 50%;
}

.outer {
  width: 3.5em;
  height: 3.5em;
  margin-left: -1.75em;
  margin-top: -1.75em;
  animation: spin 2s linear infinite;
}

.middle {
  width: 2.1em;
  height: 2.1em;
  margin-left: -1.05em;
  margin-top: -1.05em;
  animation: spin 1.75s linear reverse infinite;
}

.inner {
  width: 0.8em;
  height: 0.8em;
  margin-left: -0.4em;
  margin-top: -0.4em;
  animation: spin 1.5s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
</style>

index.ts代码:

import type { App, VNode } from 'vue'
import Loading from './index.vue'
import { createVNode, render } from 'vue';

export default {
  install(app: App) {
    const Vnode: VNode = createVNode(Loading)
    render(Vnode, document.body)
    app.config.globalProperties._loading = {
      show: Vnode.component?.exposed?.show,
      hide: Vnode.component?.exposed?.hide
    }
  }
}

2. 在main.ts中引入Loading并挂载到vue上

import { createApp } from 'vue'
import App from './App.vue'
import Loading from './components/Loading'

const app = createApp(App)

app.use(Loading)
app.mount('#app')

3. 在组件中调用show和hide方法控制loading显示与隐藏

<script setup lang="ts">
import { getCurrentInstance } from "vue";
const instance = getCurrentInstance() as any;
const loading = () => {
  instance?.proxy._loading.show();
  setTimeout(() => {
    instance?.proxy._loading.hide();
  }, 3000);
};
</script>