2016-08-15 42 views
0

在下面的示例中,我有一个简单的<table>,其中有一个复选框。我在td,tr和复选框上有点击事件。我希望能够点击复选框并停止冒泡到td和tr。一个简单的“event.stopPropagation()”效果很好。React - 我无法停止在表格中点击标签的传播

问题是,如果我想使用“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/ (查看控制台,点击事件)

+1

点击该标签实际生成*两个*事件:一个是点击标签和一个(隐含)点击复选框。您只处理复选框,但不处理标签。这是一个简单的HTML + JS示例:https://jsfiddle.net/zh55jwzv/(这不是特定的反应)。 –

回答

1

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

为了解决这个问题,添加一个单独的单击处理程序到label只包括.stopPropgation()demo):

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') 
); 
+0

您是否有意从render方法中删除标签元素?与标签关联的stopLabelPropagation在哪里? – KumarM

+0

正如@KumarM所提到的,您需要将标签添加回来。但这确实有用。所以解决方案基本上是让我的代码保持原样,但为标签添加一个“stopPropagation”处理程序。现在有道理,谢谢! – Andrew

+0

@KumarM - 谢谢。缩进存在问题,所以只是删除了该行。 –

1

标签上只是增加一个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') 
); 
+0

虽然这也起作用,但它会调用func3方法两次,尽管... – Andrew