From 30269be5b516e6cbba5ab84ca8c5b9d3a363589e Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Tue, 25 Aug 2020 11:09:28 +0800 Subject: [PATCH] refactor(CountDown): use composition api --- src/count-down/index.js | 265 +++++++++++++++++++--------------------- 1 file changed, 127 insertions(+), 138 deletions(-) diff --git a/src/count-down/index.js b/src/count-down/index.js index 233ef554e..26fc846cd 100644 --- a/src/count-down/index.js +++ b/src/count-down/index.js @@ -1,3 +1,11 @@ +import { + ref, + watch, + computed, + onActivated, + onDeactivated, + onBeforeUnmount, +} from 'vue'; import { createNamespace } from '../utils'; import { raf, cancelRaf } from '../utils/dom/raf'; import { isSameSecond, parseTimeData, parseFormat } from './utils'; @@ -23,144 +31,125 @@ export default createComponent({ emits: ['change', 'finish'], - data() { - return { - remain: 0, + setup(props, { emit, slots }) { + let rafId; + let endTime; + let counting; + let keepAlived; + + const remain = ref(0); + const timeData = computed(() => parseTimeData(remain.value)); + const timeText = computed(() => parseFormat(props.format, timeData.value)); + + const pause = () => { + counting = false; + cancelRaf(rafId); + }; + + const getCurrentRemain = () => Math.max(endTime - Date.now(), 0); + + const setRemain = (value) => { + remain.value = value; + emit('change', timeData.value); + + if (value === 0) { + pause(); + emit('finish'); + } + }; + + const microTick = () => { + rafId = raf(() => { + // in case of call reset immediately after finish + if (counting) { + setRemain(getCurrentRemain()); + + if (remain.value > 0) { + microTick(); + } + } + }); + }; + + const macroTick = () => { + rafId = raf(() => { + // in case of call reset immediately after finish + if (counting) { + const currentRemain = getCurrentRemain(); + + if ( + !isSameSecond(currentRemain, remain.value) || + currentRemain === 0 + ) { + setRemain(currentRemain); + } + + if (remain.value > 0) { + macroTick(); + } + } + }); + }; + + const tick = () => { + if (props.millisecond) { + microTick(); + } else { + macroTick(); + } + }; + + const start = () => { + if (!counting) { + endTime = Date.now() + remain.value; + counting = true; + tick(); + } + }; + + const reset = () => { + pause(); + remain.value = +props.time; + + if (props.autoStart) { + start(); + } + }; + + watch( + computed(() => props.time), + reset, + { immediate: true } + ); + + onActivated(() => { + if (keepAlived) { + counting = true; + keepAlived = false; + tick(); + } + }); + + onDeactivated(() => { + if (counting) { + pause(); + keepAlived = true; + } + }); + + onBeforeUnmount(pause); + + return (vm) => { + // @exposed-api + vm.start = start; + vm.reset = reset; + vm.pause = pause; + + return ( +
+ {slots.default ? slots.default(timeData.value) : timeText.value} +
+ ); }; }, - - computed: { - timeData() { - return parseTimeData(this.remain); - }, - - formattedTime() { - return parseFormat(this.format, this.timeData); - }, - }, - - watch: { - time: { - immediate: true, - handler() { - this.reset(); - }, - }, - }, - - activated() { - if (this.keepAlivePaused) { - this.counting = true; - this.keepAlivePaused = false; - this.tick(); - } - }, - - deactivated() { - if (this.counting) { - this.pause(); - this.keepAlivePaused = true; - } - }, - - beforeUnmount() { - this.pause(); - }, - - methods: { - // @exposed-api - start() { - if (this.counting) { - return; - } - - this.counting = true; - this.endTime = Date.now() + this.remain; - this.tick(); - }, - - // @exposed-api - pause() { - this.counting = false; - cancelRaf(this.rafId); - }, - - // @exposed-api - reset() { - this.pause(); - this.remain = +this.time; - - if (this.autoStart) { - this.start(); - } - }, - - tick() { - if (this.millisecond) { - this.microTick(); - } else { - this.macroTick(); - } - }, - - microTick() { - this.rafId = raf(() => { - /* istanbul ignore if */ - // in case of call reset immediately after finish - if (!this.counting) { - return; - } - - this.setRemain(this.getRemain()); - - if (this.remain > 0) { - this.microTick(); - } - }); - }, - - macroTick() { - this.rafId = raf(() => { - /* istanbul ignore if */ - // in case of call reset immediately after finish - if (!this.counting) { - return; - } - - const remain = this.getRemain(); - - if (!isSameSecond(remain, this.remain) || remain === 0) { - this.setRemain(remain); - } - - if (this.remain > 0) { - this.macroTick(); - } - }); - }, - - getRemain() { - return Math.max(this.endTime - Date.now(), 0); - }, - - setRemain(remain) { - this.remain = remain; - this.$emit('change', this.timeData); - - if (remain === 0) { - this.pause(); - this.$emit('finish'); - } - }, - }, - - render() { - return ( -
- {this.$slots.default - ? this.$slots.default(this.timeData) - : this.formattedTime} -
- ); - }, });