响应onChange on单选按钮触发onClick父div元素

时间:2017-06-02 08:47:35

标签: javascript html reactjs

我希望通过键盘处理更改与通过鼠标点击进行的更改不同。为此,我创建了以下组件。我的问题是,当我使用箭头键和空格来选择单选按钮时,它使用父div元素中的onClick方法,然后才使用输入元素中的onChange方法。这种行为的原因是什么?如何正确处理?



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'));
&#13;
<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>
&#13;
&#13;
&#13;

3 个答案:

答案 0 :(得分:3)

this issueW3C documentation的这一部分所示,这似乎是默认的浏览器行为。

  

当用户以非点击方式触发具有已定义激活行为的元素时,交互事件的默认操作必须是对元素执行合成点击激活步骤。

要解决此问题,请在exports.calculator = (event, context, callback) => { // TODO implement var i1 = event.key1; var i2 = event.key2; var operation = event.key3; switch(operation){ case '+' : callback(null, i1+i2 );break; case '-' : callback(null, i1-i2 );break; case '*' : callback(null, i1*i2 );break; case '/' : callback(null, i1/i2 );break; default:callback(null,"Invalid operator entered");break; } }; 处理程序中添加以下逻辑:

onClick

向GitHub用户Ro Savage致信,指出这一点。

以下是您的完整演示:

if (e.type === 'click' && e.clientX !== 0 && e.clientY !== 0) {
  // This is a real click. Do something here
}
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'));

答案 1 :(得分:2)

您可以禁用点击事件的传播:

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

答案 2 :(得分:0)

事件的顺序很重要:点击事件将在更改事件之前触发。 由于事件冒出来,父元素的onClick - 处理程序将在子元素的onChange - 处理程序之前被触发。

要解决您的具体问题,您可以听一下容器div上的keydown - 事件。在点击或更改事件之前应该触发此事件。

&#13;
&#13;
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'));
&#13;
<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>
&#13;
&#13;
&#13;