Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应和多个定时事件_Javascript_Reactjs_Timer - Fatal编程技术网

Javascript 反应和多个定时事件

Javascript 反应和多个定时事件,javascript,reactjs,timer,Javascript,Reactjs,Timer,我不熟悉React,作为练习,我尝试修改时钟示例 从…起目标是让秒数以一个间隔计数并改变 圆圈的颜色以更快的间隔显示 我试图通过使用setTimeout函数来更改圆圈来实现这一点 并在勾选函数中调用它们,但是设置超时调用未被调用 公认的 这是React的问题,并且setInterval与setTimeout冲突吗? 如果是这样,实现偏移定时事件的最佳方法是什么 谢谢你抽出时间 <!doctype html> <html> <head> <title>

我不熟悉React,作为练习,我尝试修改时钟示例 从…起目标是让秒数以一个间隔计数并改变 圆圈的颜色以更快的间隔显示

我试图通过使用
setTimeout
函数来更改圆圈来实现这一点 并在
勾选
函数中调用它们,但是
设置超时
调用未被调用 公认的

这是React的问题,并且
setInterval
setTimeout
冲突吗? 如果是这样,实现偏移定时事件的最佳方法是什么

谢谢你抽出时间

<!doctype html>
<html>
<head>
<title>Timer</title>

<script src="https://unpkg.com/react@15/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.min.js"></script>
<link rel="stylesheet" href="styles.css" >
</head>

<body>
<div id="root"></div>
</body>
<script type="text/babel">

var changed = false;

class GameDisplay extends React.Component{
  constructor(props){
    super(props);
    this.colorChange = this.colorChange.bind(this);
    this.state = {
      secondsElapsed: 0,
    };
  }

  tick(){
    setTimeout(() => this.colorChange(), 250);
    setTimeout(() => this.colorChange(), 250);
    this.colorChange();
    this.setState((prevState) => ({
      secondsElapsed: prevState.secondsElapsed + 1,
    }));
  }

  colorChange(){
    var tgt = document.getElementById("heart");
    if (changed){
      tgt.style.fill = "red";
    } else {
      tgt.style.fill = "green";
    }
    changed =  !changed;
  }

  componentDidMount(){
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount(){
    clearInterval(this.interval);
  }

  render(){
    return(
    <div>
      <h1>Seconds Elapsed: {this.state.secondsElapsed}</h1>
      <svg id="main_disp" width="300" height="300">
        <circle cx="150" cy="150" r="50" fill="black" />
        <circle id="heart" cx="150" cy="150" r="30" fill="red" />
      </svg>
    </div>
  );
  }
}

class App extends React.Component {
  render(){
    return(
      <div>
      <GameDisplay />
      </div>
    )
  };
}



ReactDOM.render(
  <App />,
  document.getElementById("root")
);
</script>
</html>

计时器
var=false;
类GameDisplay扩展了React.Component{
建造师(道具){
超级(道具);
this.colorChange=this.colorChange.bind(this);
此.state={
第二个选择:0,
};
}
勾选(){
setTimeout(()=>this.colorChange(),250);
setTimeout(()=>this.colorChange(),250);
这个.colorChange();
this.setState((prevState)=>({
secondsElapsed:prevState.secondsElapsed+1,
}));
}
变色{
var tgt=document.getElementById(“heart”);
如果(更改){
tgt.style.fill=“红色”;
}否则{
tgt.style.fill=“绿色”;
}
改变了=!改变了;
}
componentDidMount(){
this.interval=setInterval(()=>this.tick(),1000);
}
组件将卸载(){
clearInterval(这个.interval);
}
render(){
返回(
秒数:{this.state.secondsElapsed}
);
}
}
类应用程序扩展了React.Component{
render(){
返回(
)
};
}
ReactDOM.render(
,
document.getElementById(“根”)
);

TL;DR之所以看不到更改,是因为“同时”执行了两次颜色更改,一次覆盖另一次

setTimeout(() => this.colorChange(), 250);
setTimeout(() => this.colorChange(), 250);
setTimeout是异步的,并且会立即返回,因此您可以在“相同”的时间量之后安排两次颜色更改执行。尝试在500毫秒后将第二次调用设为超时,它就会工作

我在“同一时间”中使用了引号,因为setTimeout并不是那么精确(按设计),而JS是单线程的,所以这两次执行将在接下来的250ms左右依次执行。但无论如何,它们发生得太快,眼睛无法跟上,而且大多数现代浏览器都会将批处理渲染作为优化步骤,因此根本不会发生更改

==

但是因为你提到你不熟悉react,而且这是一个动手练习,我想说你可以做一些修改来更好地写这篇文章(用react术语)。请参见下面的示例:

<!doctype html>
<html>
  <head>
    <title>Timer</title>
    <script src="https://unpkg.com/react@15/dist/react.js"></script>
    <script src="https://unpkg.com/react-dom@15/dist/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.min.js"></script>
    <link rel="stylesheet" href="styles.css" >
  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">
      const merge = (x, y) => Object.assign({}, x, y)
      class GameDisplay extends React.Component {
        constructor(props) {
          super(props)
          this.state = { 
            fill: props.primaryFill,
            secondsElapsed: 0 
          }
          this.tick = this.tick.bind(this)
          this.colorChange = this.colorChange.bind(this)
        }

        tick() {
          this.colorChange();
          this.setState((prevState) => merge(prevState, {
            secondsElapsed: prevState.secondsElapsed + 1,
          }));
          setTimeout(this.colorChange, 250)
          setTimeout(this.colorChange, 500)
          setTimeout(this.colorChange, 750)
        }

        colorChange() {
          this.setState((prevState, props) => {
            const { primaryFill, secondaryFill } = props
            const oldFill = this.state.fill
            const fill = oldFill === primaryFill ? secondaryFill : primaryFill
            return merge(prevState, { fill })
          })
        }

        componentDidMount() {
          this.tick()
          this.interval = setInterval(this.tick, 1000);
        }

        componentWillUnmount(){
          clearInterval(this.interval);
        }

        render() {
          return (
            <div>
              <h1>Seconds Elapsed: {this.state.secondsElapsed}</h1>
              <svg id="main_disp" width="300" height="300">
                <circle cx="150" cy="150" r="50" fill="black" />
                <circle id="heart" cx="150" cy="150" r="30" fill={this.state.fill} />
              </svg>
            </div>
          );
        }
      }

      function App() {
        return (
          <div>
            <GameDisplay primaryFill="red" secondaryFill="green" />
          </div>
        )
      }

      ReactDOM.render(<App />, document.getElementById("root"));
    </script>
  </body>
</html>

计时器
const merge=(x,y)=>Object.assign({},x,y)
类GameDisplay扩展了React.Component{
建造师(道具){
超级(道具)
this.state={
填充:props.primaryFill,
第二个选择:0
}
this.tick=this.tick.bind(this)
this.colorChange=this.colorChange.bind(this)
}
勾选(){
这个.colorChange();
this.setState((prevState)=>merge(prevState{
secondsElapsed:prevState.secondsElapsed+1,
}));
setTimeout(this.colorChange,250)
setTimeout(this.colorChange,500)
setTimeout(this.colorChange,750)
}
变色{
this.setState((prevState,props)=>{
常量{primaryFill,secondaryFill}=props
const oldFill=this.state.fill
常量填充=旧填充===primaryFill?第二填充:primaryFill
返回合并(prevState,{fill})
})
}
componentDidMount(){
这个。勾选()
this.interval=setInterval(this.tick,1000);
}
组件将卸载(){
clearInterval(这个.interval);
}
render(){
返回(
秒数:{this.state.secondsElapsed}
);
}
}
函数App(){
返回(
)
}
render((对于密集型动画,也有例外情况,但作为一般规则,请尽量避免)
  • 如果必须对其进行变异,请尝试使用refs API而不是
    文档获取元素。getElementById
    ,请参阅
  • 如果没有理由使用一级组件,则使用功能组件, 看
  • 如果使用一些ES6+功能,代码可能会变得更干净, 看

  • Mehiel非常感谢您的时间和推荐信,这是一个很大的帮助。谢谢。