不想每个地方都重复使用elementplus的 进度条组件,就想着像v-loading一样,封装一个,方便使用。
使用
<div class="result-content" v-progress="progressValue">
//简单说明:progressValue为false时隐藏,0到100 显示进度条
代码
import { ElProgress } from "element-plus";
import { createVNode, render } from "vue";
const vProgress = {
mounted(el, binding) {
// 为每个元素创建独立的状态
el._progressState = {
mask: null,
progressContainer: null,
progressTimer: null,
progressVNode: null,
currentProgress: 0,
randomValue: 0,
// 将方法绑定到实例
updateProgress: (newVal) => {
if (newVal >= 0 && newVal <= 100) {
el._progressState.currentProgress = newVal;
// 创建遮罩和容器(如果不存在)
if (newVal === 0 && !el._progressState.mask) {
createProgressUI(el);
}
// 更新进度条
if (el._progressState.progressContainer) {
const progressVNode = createVNode(ElProgress, {
percentage: newVal,
"stroke-width": 15,
striped: true,
"striped-flow": true,
duration: 10,
"text-inside": true,
width: 200,
status: newVal >= 95 ? "success" : "",
format: () => {
return `${newVal < 95 ? "分析计算中" : "计算完成,结果准备中"} ${newVal}%`;
},
style: {
width: "50%",
fontWeight: "bold",
color: "#009265",
},
});
render(progressVNode, el._progressState.progressContainer);
}
// 当进度为100时,移除进度条和遮罩层
if (newVal === 100) {
setTimeout(() => {
cleanup(el);
}, 1500);
} else if (newVal < 100) {
// 随机延迟时间
const randomDelay = 0.5 + Math.random() * 1000;
el._progressState.randomValue += Math.random();
el._progressState.progressTimer = setTimeout(() => {
const nextVal = Math.floor(Math.min(el._progressState.randomValue, 98));
el._progressState.updateProgress(nextVal);
}, randomDelay);
}
}
}
};
if (binding.value === false) return;
el._progressState.updateProgress(binding.value || 0);
},
updated(el, binding) {
if (binding.value === false) {
cleanup(el);
return;
}
if (!el._progressState) {
vProgress.mounted(el, binding);
return;
}
// 清除之前的定时器
if (el._progressState.progressTimer) {
clearTimeout(el._progressState.progressTimer);
el._progressState.progressTimer = null;
}
el._progressState.updateProgress(binding.value || 0);
},
unmounted(el) {
cleanup(el);
}
};
// 辅助函数
function cleanup(el) {
if (!el._progressState) return;
if (el._progressState.progressTimer) {
clearTimeout(el._progressState.progressTimer);
}
if (el._progressState.mask && el.contains(el._progressState.mask)) {
el.removeChild(el._progressState.mask);
}
if (el._progressState.progressContainer && el.contains(el._progressState.progressContainer)) {
el.removeChild(el._progressState.progressContainer);
}
delete el._progressState;
}
function createProgressUI(el) {
const state = el._progressState;
if (!state || state.mask) return;
// 创建遮罩层
const mask = document.createElement("div");
mask.style.position = "absolute";
mask.style.top = "0";
mask.style.left = "0";
mask.style.width = "100%";
mask.style.height = "100%";
mask.style.backgroundColor = "rgba(215, 215, 215, 0.95)";
mask.style.display = "flex";
mask.style.justifyContent = "center";
mask.style.alignItems = "center";
mask.style.zIndex = "9999";
el.style.position = "relative";
el.style.overflow = "hidden";
el.appendChild(mask);
state.mask = mask;
// 创建进度条容器
const progressContainer = document.createElement("div");
progressContainer.style.position = "absolute";
progressContainer.style.width = "100%";
progressContainer.style.height = "100%";
progressContainer.style.zIndex = "10000";
progressContainer.style.display = "flex";
progressContainer.style.justifyContent = "center";
progressContainer.style.alignItems = "center";
el.appendChild(progressContainer);
state.progressContainer = progressContainer;
}
export default vProgress;