| <template> |
| <span> |
| {{ lastTime | format }} |
| </span> |
| </template> |
| |
| <script> |
| |
| function fixedZero (val) { |
| return val * 1 < 10 ? `0${val}` : val |
| } |
| |
| export default { |
| name: 'CountDown', |
| props: { |
| format: { |
| type: Function, |
| default: undefined |
| }, |
| target: { |
| type: [Date, Number], |
| required: true |
| }, |
| onEnd: { |
| type: Function, |
| default: () => ({}) |
| } |
| }, |
| data () { |
| return { |
| dateTime: '0', |
| originTargetTime: 0, |
| lastTime: 0, |
| timer: 0, |
| interval: 1000 |
| } |
| }, |
| filters: { |
| format (time) { |
| const hours = 60 * 60 * 1000 |
| const minutes = 60 * 1000 |
| |
| const h = Math.floor(time / hours) |
| const m = Math.floor((time - h * hours) / minutes) |
| const s = Math.floor((time - h * hours - m * minutes) / 1000) |
| return `${fixedZero(h)}:${fixedZero(m)}:${fixedZero(s)}` |
| } |
| }, |
| created () { |
| this.initTime() |
| this.tick() |
| }, |
| methods: { |
| initTime () { |
| let lastTime = 0 |
| let targetTime = 0 |
| this.originTargetTime = this.target |
| try { |
| if (Object.prototype.toString.call(this.target) === '[object Date]') { |
| targetTime = this.target |
| } else { |
| targetTime = new Date(this.target).getTime() |
| } |
| } catch (e) { |
| throw new Error('invalid target prop') |
| } |
| |
| lastTime = targetTime - new Date().getTime() |
| |
| this.lastTime = lastTime < 0 ? 0 : lastTime |
| }, |
| tick () { |
| const { onEnd } = this |
| |
| this.timer = setTimeout(() => { |
| if (this.lastTime < this.interval) { |
| clearTimeout(this.timer) |
| this.lastTime = 0 |
| if (typeof onEnd === 'function') { |
| onEnd() |
| } |
| } else { |
| this.lastTime -= this.interval |
| this.tick() |
| } |
| }, this.interval) |
| } |
| }, |
| beforeUpdate () { |
| if (this.originTargetTime !== this.target) { |
| this.initTime() |
| } |
| }, |
| beforeDestroy () { |
| clearTimeout(this.timer) |
| } |
| } |
| </script> |
| |
| <style scoped> |
| |
| </style> |