父组件中直接调用 :<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>