2017-06-02 40 views
1

我想通過鼠標點擊變化不同的方式處理由鍵盤會改變。爲此我創建了以下組件。我的問題是,當我使用箭頭鍵和空格來選擇單選按鈕時,它使用來自父div元素的onClick方法,然後使用input元素中的onChange方法。這種行爲的原因是什麼?如何正確處理?陣營的onChange單選按鈕火災的onClick父div元素

class Radio extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 

 
    this.onChange = this.onChange.bind(this); 
 
    this.onClick = this.onClick.bind(this); 
 

 
    this.state = { checked: false }; 
 
    } 
 

 
    onChange() { 
 
    this.setState({ checked: !this.state.checked }); 
 
    console.log('onChange'); 
 
    } 
 

 
    onClick() { 
 
    this.onChange(); 
 
    console.log('onClick'); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div onClick={this.onClick}> 
 
     <input 
 
      type="radio" 
 
      checked={this.state.checked} 
 
      onChange={this.onChange} 
 
     /> 
 
     Click me! 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<Radio />, document.getElementById('root'));
<div id="root"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>

回答

2

this issue看到和W3C documentation的這一部分,這似乎是一個默認瀏覽器的行爲。

當用戶以非點擊的方式觸發具有定義的激活行爲的元素時,交互事件的默認操作必須是對該元素運行合成點擊激活步驟。

要解決此問題,添加以下邏輯在onClick處理程序:

if (e.type === 'click' && e.clientX !== 0 && e.clientY !== 0) { 
    // This is a real click. Do something here 
} 

Creds到GitHub的用戶Ro Savage,指出了這一點。


這裏是一個完整的演示給你:

class Radio extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 

 
    this.onChange = this.onChange.bind(this); 
 
    this.onClick = this.onClick.bind(this); 
 

 
    this.state = { checked: false }; 
 
    } 
 

 
    onChange() { 
 
    this.setState({ checked: !this.state.checked }); 
 
    console.log('onChange'); 
 
    } 
 

 
    onClick(e) { 
 
    if (e.type === 'click' && e.clientX !== 0 && e.clientY !== 0) { 
 
     this.onChange(); 
 
     console.log('onClick'); 
 
    } else { 
 
     console.log('prevented "onClick" on keypress'); 
 
    } 
 
    } 
 

 
    render() { 
 
    return (
 
     <div onClick={this.onClick}> 
 
     <input 
 
      type="radio" 
 
      checked={this.state.checked} 
 
      onChange={this.onChange} 
 
     /> 
 
     Click me! 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<Radio />, document.getElementById('root'));
<div id="root"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>

+1

非常有趣!您的解決方案效果很好,謝謝。 –

0

您可以禁用單擊事件的傳播:

<input 
    type="radio" 
    checked={this.state.checked} 
    onClick={(e)=>{e.stopPropagation()}} 
    onChange={this.onChange} 
/> 
+0

謝謝您的回答。這個解決方案的問題在於,使用鍵盤時,單選按鈕不會被視覺檢查。有沒有辦法處理這個問題? –

0

的事件的順序很重要:單擊事件將觸發改變事件之前。 由於事件冒泡,則onClick -handler父元素將得到onChange -handler的子元素的前觸發。

要解決特定的問題,例如,你可以聽​​-event在容器-DIV。此事件應在點擊或更改事件之前觸發。

class Radio extends React.Component { 
 
    constructor(props) { 
 
    super(props); 
 

 
    this.onChange = this.onChange.bind(this); 
 
    this.onKeyUp = this.onKeyUp.bind(this); 
 

 
    this.state = { checked: false }; 
 
    } 
 

 
    onChange() { 
 
    this.setState({ checked: !this.state.checked }); 
 
    console.log('onChange'); 
 
    } 
 

 
    onKeyUp() { 
 
    console.log('onKeyUp'); 
 
    this.onChange(); 
 
    } 
 

 
    render() { 
 
    return (
 
     <div onKeyUp={this.onKeyUp}> 
 
     <input 
 
      type="radio" 
 
      checked={this.state.checked} 
 
      onChange={this.onChange} 
 
     /> 
 
     Click me! 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<Radio />, document.getElementById('root'));
<div id="root"></div> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>