运用示例
点击前往 Demo - Codepen
示例代码
<template>
<div style="display: flex; gap: 12px;">
<div v-for="item in 2" :key="item">
<el-progress
type="dashboard"
:color="colors"
:percentage="percentages[item - 1]"
></el-progress>
<div>
<el-button-group>
<el-button @click="start(item - 1)">开始</el-button>
<el-button @click="done(item - 1)">结束</el-button>
</el-button-group>
</div>
</div>
</template>
<script>
import { ProgressBar } from './xxx'
export default {
data() {
return {
percentages: [0, 0],
progressBars: [null, null],
colors: [
{color: '#f56c6c', percentage: 20},
{color: '#e6a23c', percentage: 40},
{color: '#5cb87a', percentage: 60},
{color: '#1989fa', percentage: 80},
{color: '#6f7ad3', percentage: 100}
],
};
},
methods: {
start(index) {
this.progressBars[index] = new ProgressBar({
callback: (percentage) => {
this.$set(this.percentages, index, Number((percentage * 100).toFixed(2)))
}
})
this.progressBars[index].start()
},
done(index) {
this.progressBars[index].done()
}
}
}
</script>
功能源码
class ProgressBar {
constructor({ trickleRate = 0.04, trickleSpeed = 100, callback }) {
this.intervalId = null;
this.trickleRate = trickleRate;
this.trickleSpeed = trickleSpeed;
let tempProgress = 0;
Object.defineProperty(this, "progress", {
get: () => {
return tempProgress;
},
set: (newVal) => {
tempProgress = newVal;
// 同步更新数据
callback && callback(newVal);
}
});
}
start() {
if (this.intervalId) {
return;
}
this.intervalId = setInterval(() => {
this.inc(Math.random() * this.trickleRate);
}, this.trickleSpeed);
}
clamp(val, min, max) {
if (val < min) {
return min;
}
if (val > max) {
return max;
}
return val;
}
set(val) {
this.progress = val;
return this
}
inc(val) {
const endWaitVal = 0.994;
const formatVal = this.clamp(this.progress + val, 0, endWaitVal);
// 到达既定停止值时,清除计时器
formatVal === endWaitVal && clearInterval(this.intervalId);
return this.set(formatVal)
}
stop() {
if (this.intervalId) {
clearInterval(this.intervalId);
// 清空计时器ID,便于重新发起
this.intervalId = null;
}
}
done() {
this.inc(0.012 * Math.random() * 0.5).set(1);
this.stop(); // 停止进度增加
}
}
源码介绍
类构造函数
constructor({ trickleRate = 0.04, trickleSpeed = 200, callback }) {
this.intervalId = null;
this.trickleRate = trickleRate;
this.trickleSpeed = trickleSpeed;
let tempProgress = 0;
Object.defineProperty(this, "progress", {
get: () => {
return tempProgress;
},
set: (newVal) => {
tempProgress = newVal;
// 同步更新数据
callback && callback(newVal);
}
});
}
参数
trickleRate:单次增长最高额度,默认值为 0.04(即4%)。trickleSpeed:增长时间间隔,默认值为 200ms。callback:进度发生时所调用的回调方法,该方法的首个参数为 最新进度。
QNA
Q: 为何不直接赋值?
A: 借助Object.defineProperty下属set方法,能够在进度发生变化时,及时通知该类的使用处。
Q:
get、set中,为何不直接 获取、赋值this.progress?
A:从代码解析角度出发,不难发现:在使用Object.defineProperty构建参数的过程中,参数本身仍是不存在的。因而需借助外部参数tempProgress。
set函数
set(val) {
this.progress = val;
return this
}
return this 便于 链式反应 执行