count-down.vue 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <template>
  2. <div v-if="time >= 0">
  3. <client-only>
  4. <slot v-if="isSlot"></slot>
  5. <span v-else>{{ formateTime }}</span>
  6. </client-only>
  7. </div>
  8. </template>
  9. <script>
  10. import { parseTimeData, parseFormat } from '~/utils/parseTime'
  11. export default {
  12. components: {},
  13. props: {
  14. isSlot: {
  15. type: Boolean,
  16. default: false,
  17. },
  18. time: {
  19. type: Number,
  20. default: 0,
  21. },
  22. format: {
  23. type: String,
  24. default: 'hh:mm:ss',
  25. },
  26. autoStart: {
  27. type: Boolean,
  28. default: true,
  29. },
  30. },
  31. watch: {
  32. time: {
  33. immediate: true,
  34. handler(value) {
  35. if (value) {
  36. this.reset()
  37. }
  38. },
  39. },
  40. },
  41. data() {
  42. return {
  43. timeObj: {},
  44. formateTime: 0,
  45. }
  46. },
  47. created() {},
  48. computed: {},
  49. methods: {
  50. createTimer(fn) {
  51. return setTimeout(fn, 100)
  52. },
  53. isSameSecond(time1, time2) {
  54. return Math.floor(time1) === Math.floor(time2)
  55. },
  56. start() {
  57. if (this.counting) {
  58. return
  59. }
  60. this.counting = true
  61. this.endTime = Date.now() + this.remain * 1000
  62. this.setTimer()
  63. },
  64. setTimer() {
  65. this.tid = this.createTimer(() => {
  66. let remain = this.getRemain()
  67. if (!this.isSameSecond(remain, this.remain) || remain === 0) {
  68. this.setRemain(remain)
  69. }
  70. if (this.remain !== 0) {
  71. this.setTimer()
  72. }
  73. })
  74. },
  75. getRemain() {
  76. return Math.max(this.endTime - Date.now(), 0)
  77. },
  78. pause() {
  79. this.counting = false
  80. clearTimeout(this.tid)
  81. },
  82. reset() {
  83. this.pause()
  84. this.remain = this.time
  85. this.setRemain(this.remain)
  86. if (this.autoStart) {
  87. this.start()
  88. }
  89. },
  90. setRemain(remain) {
  91. const { format } = this
  92. this.remain = remain
  93. const timeData = parseTimeData(remain)
  94. this.formateTime = parseFormat(format, timeData)
  95. this.$emit('change', timeData)
  96. if (remain === 0) {
  97. this.pause()
  98. this.$emit('finish')
  99. }
  100. },
  101. },
  102. }
  103. </script>
  104. <style lang="scss">
  105. </style>