New file |
| | |
| | | <template> |
| | | <view class="u-count-down"> |
| | | <slot> |
| | | <text class="u-count-down__text">{{ formattedTime }}</text> |
| | | </slot> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | import props from './props.js'; |
| | | import { |
| | | isSameSecond, |
| | | parseFormat, |
| | | parseTimeData |
| | | } from './utils'; |
| | | /** |
| | | * u-count-down 倒计时 |
| | | * @description 该组件一般使用于某个活动的截止时间上,通过数字的变化,给用户明确的时间感受,提示用户进行某一个行为操作。 |
| | | * @tutorial https://uviewui.com/components/countDown.html |
| | | * @property {String | Number} time 倒计时时长,单位ms (默认 0 ) |
| | | * @property {String} format 时间格式,DD-日,HH-时,mm-分,ss-秒,SSS-毫秒 (默认 'HH:mm:ss' ) |
| | | * @property {Boolean} autoStart 是否自动开始倒计时 (默认 true ) |
| | | * @property {Boolean} millisecond 是否展示毫秒倒计时 (默认 false ) |
| | | * @event {Function} finish 倒计时结束时触发 |
| | | * @event {Function} change 倒计时变化时触发 |
| | | * @event {Function} start 开始倒计时 |
| | | * @event {Function} pause 暂停倒计时 |
| | | * @event {Function} reset 重设倒计时,若 auto-start 为 true,重设后会自动开始倒计时 |
| | | * @example <u-count-down :time="time"></u-count-down> |
| | | */ |
| | | export default { |
| | | name: 'u-count-down', |
| | | mixins: [uni.$u.mpMixin, uni.$u.mixin, props], |
| | | data() { |
| | | return { |
| | | timer: null, |
| | | // 各单位(天,时,分等)剩余时间 |
| | | timeData: parseTimeData(0), |
| | | // 格式化后的时间,如"03:23:21" |
| | | formattedTime: '0', |
| | | // 倒计时是否正在进行中 |
| | | runing: false, |
| | | endTime: 0, // 结束的毫秒时间戳 |
| | | remainTime: 0, // 剩余的毫秒时间 |
| | | } |
| | | }, |
| | | watch: { |
| | | time(n) { |
| | | this.reset() |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.init() |
| | | }, |
| | | methods: { |
| | | init() { |
| | | this.reset() |
| | | }, |
| | | // 开始倒计时 |
| | | start() { |
| | | if (this.runing) return |
| | | // 标识为进行中 |
| | | this.runing = true |
| | | // 结束时间戳 = 此刻时间戳 + 剩余的时间 |
| | | this.endTime = Date.now() + this.remainTime |
| | | this.toTick() |
| | | }, |
| | | // 根据是否展示毫秒,执行不同操作函数 |
| | | toTick() { |
| | | if (this.millisecond) { |
| | | this.microTick() |
| | | } else { |
| | | this.macroTick() |
| | | } |
| | | }, |
| | | macroTick() { |
| | | this.clearTimeout() |
| | | // 每隔一定时间,更新一遍定时器的值 |
| | | // 同时此定时器的作用也能带来毫秒级的更新 |
| | | this.timer = setTimeout(() => { |
| | | // 获取剩余时间 |
| | | const remain = this.getRemainTime() |
| | | // 重设剩余时间 |
| | | if (!isSameSecond(remain, this.remainTime) || remain === 0) { |
| | | this.setRemainTime(remain) |
| | | } |
| | | // 如果剩余时间不为0,则继续检查更新倒计时 |
| | | if (this.remainTime !== 0) { |
| | | this.macroTick() |
| | | } |
| | | }, 30) |
| | | }, |
| | | microTick() { |
| | | this.clearTimeout() |
| | | this.timer = setTimeout(() => { |
| | | this.setRemainTime(this.getRemainTime()) |
| | | if (this.remainTime !== 0) { |
| | | this.microTick() |
| | | } |
| | | }, 50) |
| | | }, |
| | | // 获取剩余的时间 |
| | | getRemainTime() { |
| | | // 取最大值,防止出现小于0的剩余时间值 |
| | | return Math.max(this.endTime - Date.now(), 0) |
| | | }, |
| | | // 设置剩余的时间 |
| | | setRemainTime(remain) { |
| | | this.remainTime = remain |
| | | // 根据剩余的毫秒时间,得出该有天,小时,分钟等的值,返回一个对象 |
| | | const timeData = parseTimeData(remain) |
| | | this.$emit('change', timeData) |
| | | // 得出格式化后的时间 |
| | | this.formattedTime = parseFormat(this.format, timeData) |
| | | // 如果时间已到,停止倒计时 |
| | | if (remain <= 0) { |
| | | this.pause() |
| | | this.$emit('finish') |
| | | } |
| | | }, |
| | | // 重置倒计时 |
| | | reset() { |
| | | this.pause() |
| | | this.remainTime = this.time |
| | | this.setRemainTime(this.remainTime) |
| | | if (this.autoStart) { |
| | | this.start() |
| | | } |
| | | }, |
| | | // 暂停倒计时 |
| | | pause() { |
| | | this.runing = false; |
| | | this.clearTimeout() |
| | | }, |
| | | // 清空定时器 |
| | | clearTimeout() { |
| | | clearTimeout(this.timer) |
| | | this.timer = null |
| | | } |
| | | }, |
| | | beforeDestroy() { |
| | | this.clearTimeout() |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style |
| | | lang="scss" |
| | | scoped |
| | | > |
| | | @import "../../libs/css/components.scss"; |
| | | $u-count-down-text-color:$u-content-color !default; |
| | | $u-count-down-text-font-size:15px !default; |
| | | $u-count-down-text-line-height:22px !default; |
| | | |
| | | .u-count-down { |
| | | &__text { |
| | | color: $u-count-down-text-color; |
| | | font-size: $u-count-down-text-font-size; |
| | | line-height: $u-count-down-text-line-height; |
| | | } |
| | | } |
| | | </style> |