| | |
| | | <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;
|
| | | }
|
| | | }
|
| | | <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> |