一、js 定时器有以下两个方法:
- setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式。方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。
- setTimeout() :在指定的毫秒数后调用函数或计算表达式。
实现方式大同小异,这里以setInterval举例。
二、React 官方定时器的例子
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = {secondsElapsed: 0};
}
tick() {
this.setState((prevState) => ({
secondsElapsed: prevState.secondsElapsed + 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>Seconds Elapsed: {this.state.secondsElapsed}</div>
);
}
}
ReactDOM.render(<Timer />, mountNode);
也就是在componentDidMount()函数里设置定时,在componentWillUnmount()函数里清除定时器。这样定时器就会在页面加载的时候卸载掉定时器。tick()函数就是定期执行的函数,这里可以按照自己的需求进行设置。
这时候的定时器只会在组件生成时启动,组件卸载时停止。这样的好处是不用控制定时器,坏处是无法手动控制定时器的起停。
三、多个定时器的手动控制
import React, { Component } from 'react';
let timer1 = undefined;
let timer2 = undefined;
let timer3 = undefined;
class App extends Component {
constructor(props) {
super(props);
this.state = {secondsElapsed: 0};
}
componentDidMount() {
this.timerStart1();
this.timerStart2();
}
componentWillUnmount() {
clearInterval(timer1);
clearInterval(timer2);
}
record1 = () => {
this.setState((prevState) => ({
secondsElapsed: prevState.secondsElapsed + 1
}));
console.log("timer1");
}
record2 = () => {
console.log("timer2");
}
record3 = () => {
console.log("timer3");
}
timerStart1 = () => {
timer1 = setInterval(() => this.record1(), 1000);
}
timerStart2= () => {
timer2 = setInterval(() => this.record2(), 1000);
}
timerStart3= () => {
timer3 = setInterval(() => this.record3(), 1000);
}
timerStop1= () => {
clearInterval(timer1);
}
timerStop2= () => {
clearInterval(timer2);
}
timerStop3= () => {
clearInterval(timer3);
}
render() {
return (
<div>
<div>
Seconds Elapsed: {this.state.secondsElapsed}
</div>
<div>
<button onClick={this.timerStart1}>timerStart1</button>
<button onClick={this.timerStop1}>timerStop1</button>
</div>
<div>
<button onClick={this.timerStart2}>timerStart2</button>
<button onClick={this.timerStop2}>timerStop2</button>
</div>
<div>
<button onClick={this.timerStart3}>timerStart3</button>
<button onClick={this.timerStop3}>timerStop3</button>
</div>
</div>
);
}
}
export default App;
在这段代码里,设置了三个定时器,并且设置了6个按钮,分别取控制这三个定时器的起停。timer1和timer2,是随组件加载后就启动的,timer3是手动点击启动后才会启动。运行代码,F12看console,自己体验。
未打开定时器timer3时:
打开定时器timer3时:
由上可知:
1.定时器可以随时的打开和清除,因此可以在自己需要的周期函数中进行调用;
2.定时器是可以用变量指代,可以通过变量名清除指定的定时器;
3.上面的代码未作判断,因此会出现定时器清除不掉的情况。具体操作是:同一个定时器点击启动两次以上,当再点击清除定时器时,只能清除一个定时器。原因是:只用了一个变量,变量被覆盖,只会清除最后一个定时器。
4.针对3所述,如果对定时器无差别对待,可以采用数组的形式把变量都存储起来,伪码如下:
let timer = null;
let timerList = []
timerStart = () => {
timer = setInterval(()=> this.record(), 1000);
timerList.push(timer)
}
timerEnd = () => {
timerList.forEach((item,index)=>{ clearInterval(item) })
timerList = []
timer = 0;
}
5.针对3所述,如果每个定时器都有自己指定的任务,建议在启动定时器之前先进行检查,再启动定时,伪码如下:
timerStart = () =>{
if (timer) {
clearInterval(timer);
}
timer = setInterval(()=> this.record(), 1000);
}
timerStop = () => {
clearInterval(timer);
timer = 0;
}
参考连接:
https://juejin.im/post/5aaa248d6fb9a028b410caa0