vue倒计时实现

151 阅读1分钟

父组件

<template>
    <div class="time">
      <CountDown ref="timer" @finishTest="finishTest" />
    </div>
</template>
<script>
import CountDown from './components/countDown'
export default {
  components: {
    CountDown
  },
  beforeRouteLeave (to, from, next) {
    if (this.endTime === 0) return next()
    // 中途退出提示
    if (this.isFill) return next()
    this.$confirm('中途退出可能对成绩有所影响, 是否继续?', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
      .then(() => {
        this.$refs.timer.closeTime()
        next()
      })
      .catch()
  },
  data () {
    return {
      isFill: false, // 是否完成答卷
      endTime: 0,
      currentRow: {
      }
    }
  },
  computed: {
  },
  created () {
  },
  methods: {
    finishTest () {
      finishTest({ id: this.currentRow.id }) // 交卷接口
      this.isFill = true
      this.$router.push({ path: '' }) // 结束考试后跳转
    },
    sjzSjc (time) {
      // var s = +new Date(time) // 将YYYY-MM--DD hh-mm-ss 转成时间戳
      var s = new Date(time).getTime() // 将YYYY-MM--DD hh-mm-ss 转成时间戳
      return s
    },
    getTestData () {
      // 此处请求来的结束时间
          this.endTime = this.sjzSjc(res.data.tdDjjssj)
          if (this.endTime !== 0) this.$refs.timer && this.$refs.timer.begin(this.endTime)
        }
      }
    }
  }
}
</script>

子组件

<template>
  <div>
    <p><i class="el-icon-time" /> {{ `${hr.toString().padStart(2,'0')}: ${min.toString().padStart(2,'0')}: ${sec.toString().padStart(2,'0')}` }}</p>
    <el-button v-if="!isEnd" type="primary" size="mini" @click="open">交卷</el-button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      isEnd: false,
      time: 0,
      hr: 0,
      min: 0,
      sec: 0,
      timer: null
    }
  },
  beforeDestroy () {
    this.timer = null
  },
  methods: {
    begin (time) {
      this.time = time
      // 开始执行倒计时
      this.countdown()
      this.$message({
        type: 'success',
        message: '开始答题'
      })
    },
    countdown () {
      const end = this.time // 定义结束时间
      const now = Date.parse(new Date()) // 获取本地时间
      const msec = end - now // 定义总共所需的时间
      // 将时间戳进行格式化
      const hr = parseInt(msec / 1000 / 60 / 60 % 24)
      const min = parseInt(msec / 1000 / 60 % 60)
      const sec = parseInt(msec / 1000 % 60)
      // 倒计时结束时的操作
      const that = this
      if (hr === 0 && min === 0 && sec === 0) {
        if (this.timer) {
          clearTimeout(this.timer)
        }
        // this.$message('时间已经结束,答题完毕!')
        this.$alert('时间到,考试结束!', {
          confirmButtonText: '确定',
          callback: action => {
            this.$emit('finishTest')
            this.isEnd = true
          }
        })
        this.hr = 0
        this.min = 0
        this.sec = 0
      } else {
        // 如时间未归零则继续在一秒后执行
        this.hr = hr > 9 ? hr : '0' + hr
        this.min = min > 9 ? min : '0' + min
        this.sec = sec > 9 ? sec : '0' + sec
        if (this.timer) {
          clearTimeout(this.timer)
        }
        this.timer = setTimeout(that.countdown, 1000)
      }
    },
    closeTime () {
      clearTimeout(this.timer)
    },
    open () {
      this.$confirm('即将结束答题, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then((action) => {
        // eleUI的确定结束回调函数方法
        if (action === 'confirm') {
          this.hr = 0
          this.min = 0
          this.sec = 0
          if (this.timer) {
            clearTimeout(this.timer)
          }
          this.$emit('finishTest')
          this.isEnd = true
          this.$message({
            type: 'success',
            message: '交卷成功!'
          })
        }
      }).catch(() => {
        // 点击取消后
        this.$message({
          type: 'info',
          message: '已取消交卷'
        })
      })
    }
  }
}
</script>
<style lang="scss" scoped>
</style>