bug
jiangping
2023-11-07 64b432916af9c9218ab3f3eca614e26c542142ae
minipro_standard/uni_modules/uview-ui/components/u-count-down/u-count-down.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,163 @@
<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>