开源cool的倒计时组件,修改后也可直接使用在网页中,非常好用的一个倒计时控件
1. 组件源码
可以在cool uni中下载
<template>
<div class="cl-countdown">
<template v-for="(item, index) in list">
<div class="cl-countdown-item" :key="index" :style="[customStyle]" v-if="item.visible">
<span class="cl-countdown__number" :style="[numberStyle]">{{ item.value }}</span>
<span class="cl-countdown__splitor" :style="[splitorStyle]">{{
item.splitor
}}</span>
</div>
</template>
<div class="cl-countdown-item" v-if="isMillisecond">
<span class="cl-countdown__number">{{ millisecond }}</span>
</div>
</div>
</template>
<script>
function isArray(value) {
if (typeof Array.isArray === 'function') {
return Array.isArray(value);
} else {
return Object.prototype.toString.call(value) === '[object Array]';
}
}
/**
* countdown 倒计时
* @description 倒计时, 支持布局显示, 自定义样式
* @property {String, Array} splitor 图片链接
* @property {Array} layout 布局, ["day", "hour", "minute", "second"]
* @property {String} mode default 默认 | simple 是否精简:为00时自动隐藏,默认dfault
* @property {Number} day 还有多少天
* @property {Number} hour 还有多少小时
* @property {Number} minute 还有多少分钟
* @property {Number} second 还有多少秒
* @property {Date, String} datetime 结束时间
* @property {Boolean} isMillisecond 是否带有毫秒
* @property {Object} customStyle 自定义样式
* @property {Object} numberStyle 数字样式
* @property {Object} splitorStyle 分隔符样式
* @example <cl-countdown :day="5" />
*/
export default {
name: "countdown",
props: {
// 分隔符 [day, hour, minute, second]
splitor: {
type: [String, Array],
default: "default"
},
// 布局
layout: {
type: Array,
default: () => ["day", "hour", "minute", "second"]
},
// simple 是否精简:为00时自动隐藏
mode: {
type: String,
default: "default"
},
// 还有多少天
day: {
type: Number,
default: 0
},
// 还有多少小时
hour: {
type: Number,
default: 0
},
// 还有多少分钟
minute: {
type: Number,
default: 0
},
// 还有多少秒
second: {
type: Number,
default: 0
},
// 结束时间
datetime: [Date, String],
// 是否带有毫秒
isMillisecond: Boolean,
// 自定义样式
customStyle: Object,
// 数字样式
numberStyle: Object,
// 分隔符样式
splitorStyle: Object
},
data() {
return {
timer: null,
millisecondTimer: null,
syncFlag: false,
seconds: 0,
list: [],
millisecond: 9,
status: false
};
},
watch: {
day() {
this.changeFlag();
},
hour() {
this.changeFlag();
},
minute() {
this.changeFlag();
},
second() {
this.changeFlag();
},
datetime() {
this.changeFlag();
}
},
beforeDestroy() {
this.clear();
},
created() {
this.start();
},
methods: {
// 转成秒
toSeconds({ day = 0, hour = 0, minute = 0, second = 0, datetime }) {
if (datetime) {
return (
(new Date(datetime.replace(/-/g, "/")).getTime() - new Date().getTime()) / 1000
);
} else {
return day * 60 * 60 * 24 + hour * 60 * 60 + minute * 60 + second;
}
},
// 开始倒计时
start(options) {
let { day, hour, minute, second, datetime } = options || {};
if (!day) {
day = this.day;
}
if (!hour) {
hour = this.hour;
}
if (!minute) {
minute = this.minute;
}
if (!second) {
second = this.second;
}
if (!datetime) {
datetime = this.datetime;
}
this.seconds = this.toSeconds({
day,
hour,
minute,
second,
datetime
});
this.next();
},
// 继续倒计时
next() {
if (this.seconds <= 0) {
return;
}
if (this.status) {
return;
}
this.status = true;
// Start coundown
const next = () => {
this.countDown();
if (this.seconds <= 0) {
this.done();
return;
} else {
this.seconds--;
this.timer = setTimeout(next, 1000);
}
};
// Use setTimeout instead setInterval
next();
// milli second
if (this.isMillisecond) {
const next = () => {
this.millisecond--;
if (this.millisecond < 0) {
this.millisecond = 9;
}
this.millisecondTimer = setTimeout(next, 100);
};
next();
}
},
// 停止
stop() {
this.clear();
this.$emit("stop");
},
// 结束
done() {
this.clear();
this.$emit("done");
},
// 清除定时器
clear() {
clearTimeout(this.timer);
clearTimeout(this.millisecondTimer);
this.timer = null;
this.millisecondTimer = null;
this.status = false;
},
// 倒计时执行
countDown() {
let seconds = this.seconds;
let [day, hour, minute, second] = [0, 0, 0, 0];
day = Math.floor(seconds / (60 * 60 * 24));
hour = Math.floor(seconds / (60 * 60)) - day * 24;
minute = Math.floor(seconds / 60) - day * 24 * 60 - hour * 60;
second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
if (day < 10) {
day = "0" + day;
}
if (hour < 10) {
hour = "0" + hour;
}
if (minute < 10) {
minute = "0" + minute;
}
if (second < 10) {
second = "0" + second;
}
const obj = {
day,
hour,
minute,
second
};
let flag = day === "00";
this.list = this.layout.map((e, i) => {
let item = {
value: obj[e],
splitor: this.splitorText(i),
visible: this.mode === "simple" ? (flag ? obj[e] !== "00" : true) : true
};
if (flag) {
flag = obj[e] === "00";
}
return item;
});
this.$emit(
"change",
this.list.map(e => e.value)
);
},
// 分隔符内容
splitorText(i) {
let arr = [];
if (isArray(this.splitor)) {
arr = this.splitor;
} else {
switch (this.splitor) {
case "cn":
arr = ["天", "时", "分", "秒"];
break;
case "en":
arr = ["Day", "Hour", "Minute", "Second"];
break;
case "":
case false:
case null:
arr = ["", "", "", ""];
break;
case "default":
default:
arr = ["天", ":", ":", ""];
break;
}
}
return arr[i];
},
changeFlag() {
this.$nextTick(() => {
this.start();
});
}
}
};
</script>
<style lang="scss" scoped>
.cl-countdown {
display: inline-flex;
&__number {
display: inline-block;
height: 14px;
font-size:14px;
line-height: 14px;
text-align: center;
border-radius: 6px;
}
&__splitor {
font-size:14px;
}
&-item {
display: flex;
align-items: center;
&:first-child {
.cl-countdown__number {
margin-left: 0;
}
}
}
}
</style>
2. 组件使用
<countdown :second="3600" splitor="cn"></countdown>
3. 本代码说明
代码使用来自cool官方组件修改,查看官方组件文档di'zhi cool官方文档
评论 (0)