mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
refactor(CountDown): use composition api
This commit is contained in:
parent
d9e9879465
commit
30269be5b5
@ -1,3 +1,11 @@
|
|||||||
|
import {
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
computed,
|
||||||
|
onActivated,
|
||||||
|
onDeactivated,
|
||||||
|
onBeforeUnmount,
|
||||||
|
} from 'vue';
|
||||||
import { createNamespace } from '../utils';
|
import { createNamespace } from '../utils';
|
||||||
import { raf, cancelRaf } from '../utils/dom/raf';
|
import { raf, cancelRaf } from '../utils/dom/raf';
|
||||||
import { isSameSecond, parseTimeData, parseFormat } from './utils';
|
import { isSameSecond, parseTimeData, parseFormat } from './utils';
|
||||||
@ -23,144 +31,125 @@ export default createComponent({
|
|||||||
|
|
||||||
emits: ['change', 'finish'],
|
emits: ['change', 'finish'],
|
||||||
|
|
||||||
data() {
|
setup(props, { emit, slots }) {
|
||||||
return {
|
let rafId;
|
||||||
remain: 0,
|
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 (
|
||||||
|
<div class={bem()}>
|
||||||
|
{slots.default ? slots.default(timeData.value) : timeText.value}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
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 (
|
|
||||||
<div class={bem()}>
|
|
||||||
{this.$slots.default
|
|
||||||
? this.$slots.default(this.timeData)
|
|
||||||
: this.formattedTime}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user