2017-06-03 64 views
0

以下问题的最佳做法是什么?React.Js:在执行onClick时防止同级事件的兄弟姐妹

我有一个父组件(局)和四个子组件(GameButton)这是一个可以点击的按钮。按钮点击照亮按钮0.5秒,然后将按钮转回到初始样式。我想在一个按钮点亮时防止对其他按钮的任何点击。

class GameButton extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     illuminated:false, 
    }; 
    this.playButton = this.playButton.bind(this); 
    } 

    playButton(){ 

    if (this.props.gameActive && this.props.clickable){ 
     // lock all other buttons until this function is done executing 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     // pass the second state update in a callback function to ensure delayed execution 
     this.setState({illuminated:true}, function() { 
     // arrow function to prevent binding of this to window 
     window.setTimeout(() => { 
     this.setState({illuminated: false}); 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     },500); 
     }); 
    } 

    } 
    render() { 
    var buttonStyle = this.props.colorClass; 
    if (this.state.illuminated){ 
     buttonStyle += " illuminated-" + this.props.color; 
     console.log(buttonStyle); 
    } 
    return (
     <div className={buttonStyle} onClick={this.playButton}></div> 
    ); 
    } 
} 


class Board extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     gameActive:true, 
    }; 
    this.toggleButtonAccess = this.toggleButtonAccess.bind(this); 
    } 

    toggleButtonAccess(){ 
    this.clickable = (this.clickable) ? false : true; 
    } 

    render() { 
    return (
     <div className ="game-container"> 
     <GameButton colorClass="game-btn green" color="green" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn red" color="red" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn yellow" color="yellow" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn blue" color="blue" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 

     </div> 
    ); 
    } 
} 

到目前为止,我设法由有父(局)组成的财产this.clickable,然后切换和关闭它每一个按钮被点击与toggleAccessButton()时间去做。但是,这不起作用。有一个更好的方法吗?

+1

你应该让'clickable'成为父状态的一部分。此外,'button' HTML元素具有'disabled'属性,如果其中的表达式计算为'true',则该属性将被禁用。所以你的'GameButton'可以在渲染的''button'中有'disabled = {this.props.clickable}'。 – glhrmv

回答

1

有迹象表明,你需要改变一些东西。首先,在GameButton中,我看不到gameActive中的值。事实上,你不会为这个道具传递任何价值。如果它没有任何其他目的,您在这里没有提到,只需将其删除即可。

class GameButton extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     illuminated:false, 
    }; 
    this.playButton = this.playButton.bind(this); 
    } 

    playButton(){ 

    if (this.props.clickable){ 
     // lock all other buttons until this function is done executing 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     // pass the second state update in a callback function to ensure delayed execution 
     this.setState({illuminated:true}, function() { 
     // arrow function to prevent binding of this to window 
     window.setTimeout(() => { 
     this.setState({illuminated: false}); 
     this.props.toggleButtonAccess(); 
     console.log(this.props.clickable); 

     },500); 
     }); 
    } 

    } 
    render() { 
    var buttonStyle = this.props.colorClass; 
    if (this.state.illuminated){ 
     buttonStyle += " illuminated-" + this.props.color; 
     console.log(buttonStyle); 
    } 
    return (
     <div className={buttonStyle} onClick={this.playButton}></div> 
    ); 
    } 
} 

现在主板组件,你需要保持clickable在你的状态和使用setState来改变它在toggleButtonAccess。这里我也不明白你为什么在这个州有gameActive

class Board extends React.Component { 
    constructor(){ 
    super(); 
    this.state = { 
     gameActive:true, 
     clickable:true 
    }; 
    this.toggleButtonAccess = this.toggleButtonAccess.bind(this); 
    } 

    toggleButtonAccess(){ 
    this.setState({clickable:!this.state.clickable}); 
    } 

    render() { 
    return (
     <div className ="game-container"> 
     <GameButton colorClass="game-btn green" color="green" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn red" color="red" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn yellow" color="yellow" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     <GameButton colorClass="game-btn blue" color="blue" clickable={this.clickable} toggleButtonAccess={this.toggleButtonAccess}/> 
     </div> 
    ); 
    } 
} 

假设你有正确设置其他的东西,现在应该按预期工作。

+0

对不起,创建MWE时我忘了删除gameActive-state。 – miga89

1

我宁愿使用React状态。 在我的例子中,我切换cssClass。
下面的代码示例:

const ButtonComponent = ({className,handler,idx}) => { 
    return (< div className = { 
     className 
    } > 
    < button onClick = { 
     handler 
    } > { 
     idx 
    } < /button> </div>); 
}; 

class HolderComponent extends React.Component { 
    constructor() { 
     super(); 
     this.state = { 
     current: null 
     } 

    } 

    handler(e, idx) { 
     e.preventDefault(); 
     console.log(idx + "CURRENT"); 
     this.setState({ 
     current: idx 
     },() => { 
     const self = this; 
     setTimeout(() => { 
      self.setState({ 
      current: null 
      }); 
     }, 1000) 
     }); 
    } 

    getButtons(props = []) { 

     return props.map((btn, idx) => this.getButton(idx)); 

    } 

    getButton(idx) { 

     return (< ButtonComponent key = { 
      idx + "uniqKey" 
      } 
      className = { 
      this.state.current === idx ? "test" : "testActive" 
      } 
      handler = { 
      (e) => this.handler(e, idx) 
      } 
      isActive = { 
      this.state.current === idx 
      } 
      idx = { 
      idx 
      } 
      />) 
     } 

     render() { 
      return (<div> { 
       this.getButtons([1, 2, 3, 4]) 
      } < /div>); 

      } 

     } 

     ReactDOM.render(< HolderComponent/> , document.getElementById("app"));