uniapp 封装进度条组件

167 阅读2分钟

效果与场景

场景: 一般来说,使用进度条的情况都是在需要让用户知道真实的当前进度的场景下才会使用的

例如

  • 当前下载进度
  • 当前安装进度
  • 当前上传进度
  • ...

效果如下

image.png

组件参数

属性名描述示例
state进度条是否显示(必传)Boolean:true
isFailed任务是否失败(必传)Boolean:true
totalSize总上传数据大小(必传,单位 Bytes)Number
currentSize当前上传数据大小(必传,单位 Bytes)Number
waitText等待中的文本字符串
waitColor等待中文本的字体颜色字符串
successText成功的文本字符串
successColor成功文本的字体颜色字符串
failText失败的文本字符串
failColor失败文本的字体颜色字符串
progressBarColor进度条颜色字符串

代码

<template>
	<div class="mark-box" v-if="markShow">
		<div class="progress-container">
			<div class="progress-text" :style="{ color: props.waitColor }" v-if="progress < 100">
				{{ props.waitText }} {{ progress }} %
			</div>
			<div
				class="progress-text"
				:style="{ color: props.isFailed ? props.failColor : props.successColor }"
				v-else
			>
				{{ props.isFailed ? props.failText : props.successText }}
			</div>
			<div class="progress-bar">
				<div
					class="progress"
					:style="{ width: progress + '%', background: props.progressBarColor }"
				></div>
			</div>
		</div>
	</div>
</template>

<script setup>
	import { ref, watch, onMounted } from 'vue';

	const props = defineProps({
		state: {
			type: Boolean,
			required: true,
		},
		isFailed: {
			type: Boolean,
			required: true,
		},
		totalSize: {
			type: Number,
		},
		currentSize: {
			type: Number,
		},
		waitText: {
			type: String,
			default: '上传中',
		},
		waitColor: {
			type: String,
			default: '#F5BD00',
		},
		successText: {
			type: String,
			default: '上传成功',
		},
		successColor: {
			type: String,
			default: '#00B26A',
		},
		failText: {
			type: String,
			default: '上传失败',
		},
		failColor: {
			type: String,
			default: '#EB3941',
		},
		progressBarColor: {
			type: String,
			default: '#00B26A',
		},
	});
	const emit = defineEmits(['closeProgress']);

	let progress = ref(0); // 进度条百分比
	let markShow = ref(false); // 遮罩层是否显示
	watch(
		() => props.state,
		(val) => {
			if (val) {
				markShow.value = val;
			} else {
				setTimeout(() => {
					markShow.value = val;
					progress.value = 0;
					emit('closeProgress');
				}, 1000);
			}
		}
	);
	watch(
		() => props.currentSize,
		() => {
			if (markShow.value) {
				progress.value = ((props.currentSize / props.totalSize) * 100).toFixed(1);
				// console.log('当前进度', progress.value);
			}
		}
	);
</script>

<style lang="scss" scoped>
	.mark-box {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		background: rgba(0, 0, 0, 0.5);
		z-index: 9999;
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.progress-container {
		width: 90%;
		.progress-text {
			display: flex;
			justify-content: center;
			margin: 20rpx 0;
			font-size: 34rpx;
		}
		.progress-bar {
			height: 20px;
			border-radius: 25rpx;
			background: #eee;
			overflow: hidden;
			.progress {
				height: 100%;
				border-radius: 25rpx;
				transition: width 0.1s;
			}
		}
	}
</style>

页面使用

<myProgress
			:state="state"
			:currentSize="progressCurrentSize"
			:totalSize="progressTotalSize"
			:isFailed="isFailed"
			@closeProgress="closeProgress"
		></myProgress>
             
// 进度条相关
	let state = ref(false); // 进度条组件状态
	let isFailed = ref(false); // 是否失败
	// 关闭进度条
	function closeProgress() {
		state.value = false;
		isFailed.value = false;
	}
	let progressTotalSize = ref(0); // 总上传数据大小
	let progressCurrentSize = ref(0); // 当前上传数据大小
	// 需要使用到进度条的地方,比如下面这个函数
	function aa() {
		state.value = true;
		try {
			// 处理逻辑
		} catch (error) {
			isFailed.value = true;
		}
		state.value = false;
	}

这是基本的使用demo

我有一篇兼容多端的上传文件组件有使用进度条的场景,可以用于参考实际场景中该如何使用:

juejin.cn/post/741250…