loading组件

105 阅读1分钟

父组件中直接调用 :<Loading ref="loadingRef" />

开启loading:

nextTick(() => {
    loadingRef.value.startLoading();
  });

关闭loading:

nextTick(() => {
        loadingRef.value.closeLoading();
      });
<template>
  <div class="loading" v-if="loading">
    <div class="loading-text">正在加载中,请稍等...</div>
    <div class="loading-bar">
      <div
        class="loading-progress"
        :style="{
          width: loadingProgress + '%',
        }"
      ></div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";

const loading = ref(false);
const loadingProgress = ref(0);
const loadingInterval = ref<any>(null);

onMounted(() => {
  // startLoading()
});

const emits = defineEmits(["closeLoading"]);

const startLoading = () => {
  loading.value = true;
  loadingProgress.value = 0;
  loadingInterval.value = setInterval(() => {
    if (loadingProgress.value < 60) {
      loadingProgress.value += 10;
    } else if (loadingProgress.value < 80) {
      loadingProgress.value += 2;
    } else {
      loadingProgress.value += 1;
    }
    if (loadingProgress.value >= 98) {
      loadingProgress.value = 90;
    }
  }, 100);
};

const closeLoading = () => {
  loadingProgress.value = 100;
  setTimeout(() => {
    clearInterval(loadingInterval.value);
    emits("closeLoading");
  }, 200);
  loading.value = false;
};

defineExpose({
  startLoading, // 向外暴露组件内的方法
  closeLoading,
});
</script>
<style scoped lang="scss">
.loading {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 9999;
}

.loading-text {
  font-size: 16px;
  color: white;
  margin-bottom: 20px;
}

.loading-bar {
  width: 200px;
  height: 24px;

  background: white;
  border-radius: 18px;
  overflow: hidden;
}

.loading-progress {
  height: 100%;
  background: #9dff94;
}
</style>