Javascript React中的倒计时计时器
我在JavaScript中见过很多倒计时程序,我想让其中一个在React中工作 我借用了我在网上找到的这个功能:Javascript React中的倒计时计时器,javascript,reactjs,countdown,Javascript,Reactjs,Countdown,我在JavaScript中见过很多倒计时程序,我想让其中一个在React中工作 我借用了我在网上找到的这个功能: secondsToTime(secs){ let hours = Math.floor(secs / (60 * 60)); let divisor_for_minutes = secs % (60 * 60); let minutes = Math.floor(divisor_for_minutes / 60); let divisor_for_
secondsToTime(secs){
let hours = Math.floor(secs / (60 * 60));
let divisor_for_minutes = secs % (60 * 60);
let minutes = Math.floor(divisor_for_minutes / 60);
let divisor_for_seconds = divisor_for_minutes % 60;
let seconds = Math.ceil(divisor_for_seconds);
let obj = {
"h": hours,
"m": minutes,
"s": seconds
};
return obj;
};
然后我自己写了这段代码
initiateTimer = () => {
let timeLeftVar = this.secondsToTime(60);
this.setState({ timeLeft: timeLeftVar })
};
startTimer = () => {
let interval = setInterval(this.timer, 1000);
this.setState({ interval: interval });
};
timer = () => {
if (this.state.timeLeft >0){
this.setState({ timeLeft: this.state.timeLeft -1 });
}
else {
clearInterval(this.state.interval);
//this.postToSlack();
}
};
当前单击一次,它会将屏幕上的时间设置为:剩余时间:1米:0秒
但它并没有将其缩减为剩余时间:0 m:59 s,然后再缩减为剩余时间:0 m:58 s等
我想我需要用一个不同的参数再次调用这个函数。我该怎么做呢
编辑:我忘了说,我想要功能,以便我可以使用秒到分和秒问题在于您的“this”值。
计时器函数无法访问“状态”属性,因为它在不同的上下文中运行。我建议你这样做:
...
startTimer = () => {
let interval = setInterval(this.timer.bind(this), 1000);
this.setState({ interval });
};
正如您所看到的,我在计时器函数中添加了一个“bind”方法。这允许计时器在调用时访问react组件的相同“This”(这是使用javascript时的主要问题/改进)
另一个选项是使用另一个箭头功能:
startTimer = () => {
let interval = setInterval(() => this.timer(), 1000);
this.setState({ interval });
};
您必须在剩余的秒数(每次调用间隔)内每隔一秒设置一次状态。下面是一个例子:
类示例扩展了React.Component{
构造函数(){
超级();
this.state={time:{},秒数:5};
这个计时器=0;
this.startTimer=this.startTimer.bind(this);
this.countDown=this.countDown.bind(this);
}
第二次(秒){
让小时数=数学楼层(秒/(60*60));
让除数为分钟=s%(60*60);
让分钟=数学地板(除数为分钟/60);
让除数为秒=除数为分钟%60;
设秒=Math.ceil(除数为秒);
设obj={
“h”:小时,
“m”:分钟,
“s”:秒
};
返回obj;
}
componentDidMount(){
让timeLeftVar=this.secondsToTime(this.state.seconds);
this.setState({time:timeLeftVar});
}
startTimer(){
如果(this.timer==0&&this.state.seconds>0){
this.timer=setInterval(this.countDown,1000);
}
}
倒计时{
//移除一秒钟,设置状态以便重新渲染。
设秒数=this.state.seconds-1;
这是我的国家({
时间:这个。秒到秒(秒),
秒:秒,
});
//检查我们是否在零位。
如果(秒==0){
clearInterval(这个计时器);
}
}
render(){
返回(
开始
m:{this.state.time.m}s:{this.state.time.s}
);
}
}
ReactDOM.render(,document.getElementById('View'))代码>
setInterval的一个缺点是它会减慢主线程的速度。您可以使用requestAnimationFrame
执行倒计时,以防止出现这种情况。例如,这是我的通用倒计时组件:
class Timer extends Component {
constructor(props) {
super(props)
// here, getTimeRemaining is a helper function that returns an
// object with { total, seconds, minutes, hours, days }
this.state = { timeLeft: getTimeRemaining(props.expiresAt) }
}
// Wait until the component has mounted to start the animation frame
componentDidMount() {
this.start()
}
// Clean up by cancelling any animation frame previously scheduled
componentWillUnmount() {
this.stop()
}
start = () => {
this.frameId = requestAnimationFrame(this.tick)
}
tick = () => {
const timeLeft = getTimeRemaining(this.props.expiresAt)
if (timeLeft.total <= 0) {
this.stop()
// ...any other actions to do on expiration
} else {
this.setState(
{ timeLeft },
() => this.frameId = requestAnimationFrame(this.tick)
)
}
}
stop = () => {
cancelAnimationFrame(this.frameId)
}
render() {...}
}
类计时器扩展组件{
建造师(道具){
超级(道具)
//在这里,getTimeRemaining是一个帮助函数,它返回
//对象的{total,seconds,minutes,hours,days}
this.state={timeLeft:getTimeRemaining(props.expiresAt)}
}
//等待组件安装完毕,以启动动画帧
componentDidMount(){
这个。开始()
}
//通过取消先前计划的任何动画帧进行清理
组件将卸载(){
这个
}
开始=()=>{
this.frameId=requestAnimationFrame(this.tick)
}
勾号=()=>{
const timeLeft=getTimeRemaining(this.props.expiresAt)
if(timeLeft.total this.frameId=requestAnimationFrame(this.tick)
)
}
}
停止=()=>{
cancelAnimationFrame(此.frameId)
}
render(){…}
}
类示例扩展了React.Component{
构造函数(){
超级();
this.state={time:{},秒数:5};
这个计时器=0;
this.startTimer=this.startTimer.bind(this);
this.countDown=this.countDown.bind(this);
}
第二次(秒){
让小时数=数学楼层(秒/(60*60));
让除数为分钟=s%(60*60);
让分钟=数学地板(除数为分钟/60);
让除数为秒=除数为分钟%60;
设秒=Math.ceil(除数为秒);
设obj={
“h”:小时,
“m”:分钟,
“s”:秒
};
返回obj;
}
componentDidMount(){
让timeLeftVar=this.secondsToTime(this.state.seconds);
this.setState({time:timeLeftVar});
}
startTimer(){
如果(this.timer==0&&this.state.seconds>0){
this.timer=setInterval(this.countDown,1000);
}
}
倒计时{
//移除一秒钟,设置状态以便重新渲染。
设秒数=this.state.seconds-1;
这是我的国家({
时间:这个。秒到秒(秒),
秒:秒,
});
//检查我们是否在零位。
如果(秒==0){
clearInterval(这个计时器);
}
}
render(){
返回(
开始
m:{this.state.time.m}s:{this.state.time.s}
);
}
}
ReactDOM.render(,document.getElementById('View'))代码>
这是一个使用钩子的解决方案,计时器组件,我正在用钩子复制上面相同的逻辑
import React from 'react'
import { useState, useEffect } from 'react';
const Timer = (props:any) => {
const {initialMinute = 0,initialSeconds = 0} = props;
const [ minutes, setMinutes ] = useState(initialMinute);
const [seconds, setSeconds ] = useState(initialSeconds);
useEffect(()=>{
let myInterval = setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
}
if (seconds === 0) {
if (minutes === 0) {
clearInterval(myInterval)
} else {
setMinutes(minutes - 1);
setSeconds(59);
}
}
}, 1000)
return ()=> {
clearInterval(myInterval);
};
});
return (
<div>
{ minutes === 0 && seconds === 0
? null
: <h1> {minutes}:{seconds < 10 ? `0${seconds}` : seconds}</h1>
}
</div>
)
}
export default Timer;
从“React”导入React
从“react”导入{useState,useEffect};
常量计时器=(道具:任意)=>{
常量{initialMinute=0,initialSeconds=0}=props;
const[minutes,setMinutes]=使用状态(initialMinute);
const[seconds,setSeconds]=使用状态(initialSeconds);
useffect(()=>{
让myInterval=setInterval(()=>{
如果(秒>0){
设置秒(秒-1);
}
如果(秒===0){
如果(分钟===0){
清除间隔(myInterval)
}否则{
设置分钟数(分钟-1);
设置秒(59);
}
}
}, 1000)
return()=>{
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor() {
super();
this.state = {
hours: 0,
minutes: 0,
seconds:0
}
this.hoursInput = React.createRef();
this.minutesInput= React.createRef();
this.secondsInput = React.createRef();
}
inputHandler = (e) => {
this.setState({[e.target.name]: e.target.value});
}
convertToSeconds = ( hours, minutes,seconds) => {
return seconds + minutes * 60 + hours * 60 * 60;
}
startTimer = () => {
this.timer = setInterval(this.countDown, 1000);
}
countDown = () => {
const { hours, minutes, seconds } = this.state;
let c_seconds = this.convertToSeconds(hours, minutes, seconds);
if(c_seconds) {
// seconds change
seconds ? this.setState({seconds: seconds-1}) : this.setState({seconds: 59});
// minutes change
if(c_seconds % 60 === 0 && minutes) {
this.setState({minutes: minutes -1});
}
// when only hours entered
if(!minutes && hours) {
this.setState({minutes: 59});
}
// hours change
if(c_seconds % 3600 === 0 && hours) {
this.setState({hours: hours-1});
}
} else {
clearInterval(this.timer);
}
}
stopTimer = () => {
clearInterval(this.timer);
}
resetTimer = () => {
this.setState({
hours: 0,
minutes: 0,
seconds: 0
});
this.hoursInput.current.value = 0;
this.minutesInput.current.value = 0;
this.secondsInput.current.value = 0;
}
render() {
const { hours, minutes, seconds } = this.state;
return (
<div className="App">
<h1 className="title"> (( React Countdown )) </h1>
<div className="inputGroup">
<h3>Hrs</h3>
<input ref={this.hoursInput} type="number" placeholder={0} name="hours" onChange={this.inputHandler} />
<h3>Min</h3>
<input ref={this.minutesInput} type="number" placeholder={0} name="minutes" onChange={this.inputHandler} />
<h3>Sec</h3>
<input ref={this.secondsInput} type="number" placeholder={0} name="seconds" onChange={this.inputHandler} />
</div>
<div>
<button onClick={this.startTimer} className="start">start</button>
<button onClick={this.stopTimer} className="stop">stop</button>
<button onClick={this.resetTimer} className="reset">reset</button>
</div>
<h1> Timer {hours}: {minutes} : {seconds} </h1>
</div>
);
}
}
export default App;