【问题标题】:React - I can't stop propagation of a label click within a tableReact - 我无法停止在表格中传播标签点击
【发布时间】:2016-12-21 19:54:56
【问题描述】:

在下面的例子中,我有一个简单的<table>,里面有一个复选框。我在 td、tr 和复选框上有点击事件。我希望能够单击复选框并停止冒泡到 td 和 tr。一个简单的“event.stopPropagation()”效果很好。

问题是,如果我想使用“htmlFor”将<label> 连接到复选框,则单击标签时事件不会停止冒泡(即使单击复选框本身仍然可以正常工作) )。更奇怪的是,冒泡似乎以一种奇怪的顺序发生(如复选框点击最后收到!)。

代码如下:

var Hello = React.createClass({
  func1(e){
    console.log('tr was clicked')
  },
  func2(e){
    console.log('td was clicked')
  },
  func3(e){
    e.stopPropagation();
    console.log('Checkbox was clicked')
  },
  render: function() {
    return <table>
        <tbody>
        <tr onClick={this.func1}>
          <td onClick={this.func2}>
            <input id="thing" type="checkbox" onClick={this.func3} />                                   
            <label htmlFor="thing"> label for checkbox</label>
          </td>
        </tr>
      </tbody>
    </table>;
  }
});

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

...这是小提琴: https://jsfiddle.net/69z2wepo/52785/ (查看控制台的点击事件)

【问题讨论】:

  • 点击标签实际上会产生两个事件:一个用于点击标签,一个(隐式)点击复选框。您只处理复选框,而不是标签。这是一个简单的 HTML + JS 示例:jsfiddle.net/zh55jwzv(这不是特定于反应的)。

标签: reactjs


【解决方案1】:

尝试使用 span 包装并将evt.stopPropagation() 添加到 span 的 onClick

<span onClick={evt => evt.stopPropagation()}>
   <input id="thing" type="checkbox" onClick={this.func3} />                                   
   <label htmlFor="thing"> label for checkbox</label>
</span>

【讨论】:

    【解决方案2】:

    label 没有自己的点击处理程序,并且无法停止传播,因此当您点击label 时,会发生正常的事件冒泡。这意味着所有父级的事件处理程序都以正确的顺序调用。另外,由于htmlForcheckbox点击处理程序也会被触发,但不是作为事件冒泡的一部分。

    要解决此问题,请向仅包含.stopPropgation() (demo) 的label 添加单独的点击处理程序:

    var Hello = React.createClass({
      func1(e){
        console.log('tr was clicked')
      },
      func2(e){
        console.log('td was clicked')
      },
      func3(e){
        e.stopPropagation();
        console.log('Checkbox was clicked')
      },
      stopLabelPropagation(e) {
        e.stopPropagation();
      },
      render: function() {
        return <table>
            <tbody>
            <tr onClick={this.func1}>
              <td onClick={this.func2}>
                <input id="thing" type="checkbox" onClick={this.func3} />                                     
                <label htmlFor="thing" onClick={ this.stopLabelPropagation }>label for checkbox</label>
              </td>
            </tr>
          </tbody>
        </table>;
      }
    });
    
    ReactDOM.render(
      <Hello name="World" />,
      document.getElementById('container')
    );
    

    【讨论】:

    【解决方案3】:

    只需在标签上添加一个 onClick,具有相同的功能绑定即可。这是代码和相关的 JSBin:https://jsbin.com/caneqi/2/edit?html,js,output

    var Hello = React.createClass({
      func1(e){
        console.log('tr was clicked')
      },
      func2(e){
        console.log('td was clicked')
      },
      func3(e){
        e.stopPropagation();
        console.log('Checkbox was clicked')
      },
      render: function() {
        return <table>
            <tbody>
            <tr onClick={this.func1}>
              <td onClick={this.func2}>
                <input id="thing" type="checkbox" onClick={this.func3} />                                   
                <label htmlFor="thing" onClick={this.func3}> label for checkbox</label>
              </td>
            </tr>
          </tbody>
        </table>;
      }
    });
    
    ReactDOM.render(
      <Hello name="World" />,
      document.getElementById('container')
    );
    

    【讨论】:

    • 虽然这也有效,但它会调用 func3 方法两次...
    猜你喜欢
    • 1970-01-01
    • 2015-09-06
    • 2015-11-20
    • 2021-03-25
    • 2023-03-23
    • 2018-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多