vue倒计时实现以及自己项目中bug产生与解决

这个模块功能上线是在前两个月,今天打开群一看,说倒计时有bug。当剩余时间为一天的时候就会出现0天0时0分。

实现思路,和网上大多数都很相似,直接拎出来不解释了。

<template>
    <div>
      <div class="countDown" v-if="type == 1">{{ `${day}天${hr}:${min}:${sec}` }}</div>
      <div class="countDown" v-else-if="type == 2">
        <span class="task_time">{{ day }}</span>
        <span>天</span>
        <span class="task_time">{{ hr }}</span>
        <span>时</span>
        <span class="task_time">{{ min }}</span>
        <span>分</span>
        <span class="task_time">{{ sec }}</span>
        <span>后截止</span>
      </div>
      <div class="countDown" v-else-if="type == 3">{{ `${day}天 ${hr}小时 ${min}分 ${sec}秒` }}</div>
      <div class="countDown no_background" v-else-if="type == 4">{{ `${day}天${hr}:${min}:${sec}` }}</div>
    </div>
  </template>
  
  <script>
  import moment from 'moment'
  //倒计时 子组件,设定 三天之内显示倒计时,开始时间 + 到期时间 - 当前时间 = 倒计时
  export default {
    name: 'count-down',
    props: {
      start: {
        type: String,
        default: '2023-10-15 19:31:00'
      },
      end: {
        type: String,
        default: '2023-10-16 19:31:00'
      },
      duration: {
        type: Number,
        default: 72 * 60 * 60 * 1000
      },
      type: {
        type: [Number, String],
        default: 1
      }
    },
    mounted () {
      this.countdown()
    },
    destroyed () {
      clearTimeout(this.timer)
    },
    methods: {
      countdown () {
        let start = moment(this.start).format('YYYY-MM-DD HH:mm:ss');
        console.log('start:', start)
        // const end = Date.parse(new Date(start)) + this.duration
        // const now = Date.parse(new Date())
        const end =  new Date(start).getTime() + this.duration;
        console.log('end:', end)
        
        const now = Date.now();
        
        console.log('now:', now)
        
        const msec = end - now
        console.log('msec:', msec)
        if (msec <= 0) {
          this.day = 0
          this.hr = 0
          this.min = 0
          this.sec = 0
          clearTimeout(this.timer)
          return
        }
        // let day = parseInt(msec / 1000 / 60 / 60 / 24)
        // let hr = parseInt(msec / 1000 / 60 / 60 % 24)
        // let min = parseInt(msec / 1000 / 60 % 60)
        // let sec = parseInt(msec / 1000 % 60)
        let day = Math.floor(msec / (1000 * 60 * 60 * 24));
        let hr = Math.floor((msec / (1000 * 60 * 60)) % 24);
        let min = Math.floor((msec / (1000 * 60)) % 60);
        let sec = Math.floor((msec / 1000) % 60);
        
        this.day = day
        this.hr = hr > 9 ? hr : '0' + hr
        this.min = min > 9 ? min : '0' + min
        this.sec = sec > 9 ? sec : '0' + sec
        this.timer = setTimeout(() => {
          this.countdown()
        }, 1000)
      },
    },
    data () {
      return {
        timer: null,
        day: '',
        hr: '',
        min: '',
        sec: ''
      }
    }
  }
  </script>
  
  <style lang="scss" scoped>
  .countDown {
      text-align: center;
      background: linear-gradient(90deg, #FFE6E6 0%, rgba(255,230,230,0) 100%);
      border-radius: 4px 0px 0px 4px;
      span {
          font-size: 12px;
          font-family: SourceHanSansSC-Regular, SourceHanSansSC;
          font-weight: 400;
          color: #f87474;
      }
      .task_time {
          border-radius: 2px;
          color: #FFFFFF;
          padding: 0 2px;
          background-color: #f54646;
      }
  }
  .no_background {
    background: transparent;
    color: #E53232;
  }
  </style>
  

组件封装的没啥大问题,倒计时天数的逻辑也对。问题出现在,调用时候的duration传值。

假如显示三天之内的倒计时,需要判断剩余天数是否小于等于2同时还要计算时、分、 秒是大于还是小于和等于0。这块计算难度就增加了,额外增加工作量。当时匆忙上线,没考虑那么多逻辑,大家引以为戒避免返工。

后端传值

 "residue_days": 1,
 "residue_hours": 5,
 "residue_minutes": 36,
 "end_time": "2024-01-18T17:47:00",
 "created_at": "2024-01-06T17:47:38",

第二种:既然有了开始时间和结束时间,就直接传值,要显示三天内倒计时就用v-if/v-show判断 residue_days <= 2。

countdown() {
        // 假设 start 和 end 是已经定义好的日期字符串

        // 使用 moment.js 处理和转换时间
        // 注意:这假设您的环境中已经安装并引入了 moment.js

        let startMoment = moment(this.start);
        let endMoment = moment(this.end);

        // 计算结束时间和当前时间的差异
        let now = moment(); // 当前时间
        let duration = endMoment.diff(now); // 使用 moment.js 的 diff 函数来获取毫秒差
        // 进行倒计时
        if (duration <= 0) {
          // 倒计时已结束
          this.day = 0
          this.hr = 0
          this.min = 0
          this.sec = 0
          // 清理定时器并进行后续处理
          clearTimeout(this.timer);
          return
        } else {
          // 更新倒计时时间

          // 注意:以下的时间单位计算使用了向下取整 Math.floor 方法,
          // 因为我们想要获得完整的小时、分钟或者秒数
          let day = Math.floor(duration / (1000 * 60 * 60 * 24));
          let hr = Math.floor((duration / (1000 * 60 * 60)) % 24);
          let min = Math.floor((duration / (1000 * 60)) % 60);
          let sec = Math.floor((duration / 1000) % 60);

          // 更新倒计时显示
          this.day = day;
          this.hr = hr < 10 ? '0' + hr : hr;
          this.min = min < 10 ? '0' + min : min;
          this.sec = sec < 10 ? '0' + sec : sec;

          // 递归调用以更新倒计时
          this.timer = setTimeout(() => {
            this.countdown();
          }, 1000);
        }
      }

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值