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