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