CountDownTimer.jsx
import React from "react";
import styled from "styled-components";
import WebWorker from "../../utils/worker";
let work = function() {
let timer = null;
this.onmessage = e => {
const { endTime, state } = e.data;
if (state === "stop") {
if (timer) {
clearInterval(timer);
timer = null;
}
return;
} else if (state === "start") {
let interval = 1000;
if (!timer) {
timer = setInterval(() => {
this.postMessage(endTime - new Date().getTime());
}, interval);
}
}
};
};
let worker = new WebWorker(work);
/**
* 计算相对时间字符串
* @param {number} time 13位时间戳
*/
function relativeTime(time) {
if (time <= 0) {
return "00:00";
}
const minute = Number.parseInt(time / 1000 / 60, 10);
const second = Number.parseInt((time / 1000) % 60, 10);
return `${minute > 9 ? minute : "0" + minute}:${
second > 9 ? second : "0" + second
}`;
}
export default function CountDownTimer({
endTime,
onEnd = Function.prototype
}) {
const initTime = relativeTime(endTime - new Date().getTime());
let [time, setTime] = React.useState(initTime);
worker.onmessage = e => {
if (e.data <= 0) {
worker.postMessage({ state: "stop" });
return;
}
setTime(relativeTime(e.data));
};
React.useEffect(() => {
worker.postMessage({
state: "start",
endTime: Number.parseInt(endTime, 10)
});
return function() {
worker.postMessage({ state: "stop" });
};
}, [endTime]);
React.useEffect(() => {
if (time === "00:00") {
return function() {
onEnd();
worker.postMessage({ state: "stop" });
};
}
}, [time, endTime, onEnd]);
const Time = styled.span`
font-size: 1.6rem;
font-weight: 700;
vertical-align: middle;
`;
return (
<div>
倒计时:<Time>{time}</Time>
</div>
);
}
worker.js
export default class WebWorker {
constructor(worker) {
const code = worker.toString();
const blob = new Blob([`(${code})()`]);
return new Worker(URL.createObjectURL(blob));
}
}
暂无评论。