用vue3封装一个进度条

441 阅读1分钟
// LoadingProgress.vue

<script setup lang="ts">
import { watch, ref, onBeforeMount } from "vue";
import { Progress } from "ant-design-vue";

const props = defineProps<{ loading: boolean }>();
const baseClass = "loading-process";
const initStep = 5;
const range: Record<string, number> = {
    0: 6,
    10: 5,
    20: 4,
    30: 3,
    40: 2,
    50: 1,
    60: 0.5,
    70: 0.1,
    80: 0.05,
    90: 0.01,
};
let timeout: null | number = null;
const show = ref(true);
const percent = ref(0);
let step = initStep;
const frequency = 30;

watch(
    () => props.loading,
    (value: boolean) => {
        if (value) {
            show.value = true;
            percentHandle();
        } else {
            percent.value = 100;
            const selfTimeout = setTimeout(() => {
                percent.value = 0;
                show.value = false;
                clearTimeout(selfTimeout);
                if (timeout) {
                    clearTimeout(timeout);
                }
            }, 1000);
        }
    },
);

onBeforeMount(() => {
    if (timeout) {
        clearTimeout(timeout);
    }
});

function percentHandle() {
    percent.value += step;
    step = range[(parseInt((percent.value / 10).toString()) * 10).toString()];
    if (percent.value > 95) {
        step = 0.001;
    }
    if (percent.value > 98) {
        step = 0.0001;
    }
    if (percent.value > 100) {
        percent.value = 100;
    }
    if (props.loading) {
        if (timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(() => percentHandle(), frequency);
    }
}
</script>

<template>
    <div :class="baseClass" v-show="show">
        <Progress :percent="percent" :show-info="false" size="small" />
    </div>
</template>

<style lang="scss">
$rootClass: "loading-process";
$height: 2px;

.#{$rootClass} {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    top: -4px;
    height: $height;
    display: flex;
    align-items: center;

    > .ant-progress {
        div {
            height: $height !important;
            line-height: $height;
        }

        .ant-progress-inner {
            background-color: transparent !important;
        }
    }
}
</style>

思路:

接收一个loading属性来控制进度条的显示

监听loading的变化,为true,就用定时器不停的循环使percent不断增加,当为false,把定时器清除,进度条也隐藏

项目中对进度条的需求不是一次性的,而是根据父组件的情况要多次出现进度条,所以当loading为false后,还得做一些重置操作