view部分
<div class="endtime-custom2">
距离竞价截止时间
<span v-if="count.showCountDown">
<count-down class="endtime-custom" ref="countDown" :time="count.time" millisecond format="HH:mm:ss:SS" :autoStart="false"></count-down>
</span>
<span v-else>{{count.title}}</span>
</div>
JS部分
import countDown from '@/components/pms/countDown/countDown'
components: {
countDown
},
data () {
return {
count:{
time: 60 *60 * 1000 * 24,
showCountDown:false,
title:'竞价已结束'
}
}
}
在components中定义自定义组件新建 countDown/countDown.vue文件
<div :class="bem()">
<slot v-bind:row="timeData">{{ formattedTime }}</slot>
</div>
</template>
<script>
const SECOND = 1000;
const MINUTE = 60 * SECOND;
const HOUR = 60 * MINUTE;
const DAY = 24 * HOUR;
function parseTimeData(time) {
const days = Math.floor(time / DAY);
const hours = Math.floor(time % DAY / HOUR);
const minutes = Math.floor(time % HOUR / MINUTE);
const seconds = Math.floor(time % MINUTE / SECOND);
const milliseconds = Math.floor(time % SECOND);
return { days, hours, minutes, seconds, milliseconds };
}
function parseFormat(format, timeData) {
var days = timeData.days;
var hours = timeData.hours,
minutes = timeData.minutes,
seconds = timeData.seconds,
milliseconds = timeData.milliseconds;
if (format.indexOf('DD') === -1) {
hours += days * 24;
} else {
format = format.replace('DD', padZero(days));
}
if (format.indexOf('HH') === -1) {
minutes += hours * 60;
} else {
format = format.replace('HH', padZero(hours));
}
if (format.indexOf('mm') === -1) {
seconds += minutes * 60;
} else {
format = format.replace('mm', padZero(minutes));
}
if (format.indexOf('ss') === -1) {
milliseconds += seconds * 1000;
} else {
format = format.replace('ss', padZero(seconds));
}
if (format.indexOf('S') !== -1) {
var ms = padZero(milliseconds, 3);
if (format.indexOf('SSS') !== -1) {
format = format.replace('SSS', ms);
} else if (format.indexOf('SS') !== -1) {
format = format.replace('SS', ms.slice(0, 2));
} else {
format = format.replace('S', ms.charAt(0));
}
}
return format;
}
function isSameSecond(t1, t2) {
return Math.floor(t1 / 1000) === Math.floor(t2 / 1000);
}
function padZero(num, targetLength) {
if (targetLength === void 0) {
targetLength = 2;
}
var str = num + '';
while (str.length < targetLength) {
str = '0' + str;
}
return str;
}
const raf = fn => window.requestAnimationFrame.call(window, fn);
const cancelRaf = id => window.cancelAnimationFrame.call(window, id);
export default {
name: 'count-down',
data() {
return {
remain: 0
};
},
props: {
millisecond: Boolean, // 毫秒级渲染
time: { type: [Number, String], default: 0 },
format: { type: String, default: 'HH:mm:ss' },
autoStart: { type: Boolean, default: true }
},
activated() {
if (this.keepAlivePaused) {
this.counting = true;
this.keepAlivePaused = false;
this.tick();
}
},
methods: {
start() {
if (this.counting) return;
this.counting = true;
this.endTime = Date.now() + this.remain;
this.tick();
},
pause() {
this.counting = false;
cancelRaf(this.rafId);
},
reset() {
this.pause();
this.remain = +this.time;
if (this.autoStart) {
this.start();
}
},
tick() {
if (!(typeof window !== 'undefined')) return;
if (this.millisecond) {
this.microTick();
} else {
this.macroTick();
}
},
microTick() {
this.rafId = raf(() => {
/* istanbul ignore if */
// 如果呼叫结束后立即重置
if (!this.counting) return;
this.setRemain(this.getRemain());
if (this.remain > 0) {
this.microTick();
}
});
},
macroTick() {
this.rafId = raf(() => {
/* istanbul ignore if */
if (!this.counting) return;// 如果呼叫结束后立即重置
var remain = this.getRemain();
if (!isSameSecond(remain, this.remain) || remain === 0) {
this.setRemain(remain);
}
if (this.remain > 0) {
this.macroTick();
}
});
},
getRemain() {
return Math.max(this.endTime - Date.now(), 0);
},
setRemain(remain) {
this.remain = remain;
this.$emit('change', this.timeData);
if (remain === 0) {
this.pause();
this.$emit('finish');
}
},
createBem(name) {
/**
* bem helper
* b() // 'button'
* b('text') // 'button__text'
* b({ disabled }) // 'button button--disabled'
* b('text', { disabled }) // 'button__text button__text--disabled'
* b(['disabled', 'primary']) // 'button button--disabled button--primary'
*/
return function (el, mods) {
function gen(name, mods) {
if (!mods) return '';
if (typeof mods === 'string') return " " + name + "--" + mods;
if (Array.isArray(mods)) return mods.reduce((ret, item) => ret + gen(name, item), '');
return Object.keys(mods).reduce((ret, key) => ret + (mods[key] ? gen(name, key) : ''), '');
}
if (el && typeof el !== 'string') {
mods = el; el = '';
}
el = el ? name + "__" + el : name;
return "" + el + gen(el, mods);
};
}
},
computed: {
timeData() {
return parseTimeData(this.remain);
},
formattedTime() {
return parseFormat(this.format, this.timeData);
},
bem() {
return (...cls) => this.createBem(this.$options.name)(...cls);
}
},
watch: {
time: {
immediate: true,
handler: 'reset'
}
},
deactivated() {
if (this.counting) {
this.pause();
this.keepAlivePaused = true;
}
},
beforeDestroy() {
this.pause();
},
}
</script>
<style scoped>
.count-down {
color: #323233;
font-size: 14px;
line-height: 20px;
}
</style>