[英]Make a button inside an element clickable while the element itself is also clickable
I have a simple sidebar, that has a bunch of list items in it, and a button right next to the list item, like so: 我有一个简单的侧边栏,其中有很多列表项,并且在列表项旁边有一个按钮,如下所示:
I attached a click handler to the <li>
element like in the code below: 我将点击处理程序附加到
<li>
元素,如下面的代码所示:
<li className="note" onClick={()=> props.selectNote(props.note)} role="button">
<button className="delete-note" onClick={() => console.log('Fired')}>Delete dis</button>
<span className="updated-at">2hr</span>
<div className="note-content">
<h4 className="note-title">
{title}
</h4>
<p className="note-preview">
{notePreview.substr(0, 80)}...
</p>
</div>
</li>
But as expected, when I click the button next to it, the actual li
gets clicked and not the button inside it. 但是正如预期的那样,当我单击旁边的按钮时,实际的
li
会被单击,而不是其内部的按钮。 I think this is some sort of issue with how the event bubbles, and how it's a bad practice to attach onClick
handlers to non-interactive elements (My ESLint says that). 我认为这与事件如何冒泡以及将
onClick
处理程序附加到非交互式元素(这是我的ESLint所说)的不良做法有关。
What I want instead : 我想要的是 :
onClick
event fire. onClick
事件。 onClick
event on the button, and not the <li>
. onClick
事件,而不是<li>
。 <li data-is-parent className="note" onClick={(e)=> e.target.getAttribute('data-is-parent') && props.selectNote(props.note)} role="button">
<button className="delete-note" onClick={() => console.log('Foreground Fired')}>Delete dis</button>
<span className="updated-at">2hr</span>
<div className="note-content">
<h4 className="note-title">
{title}
</h4>
<p className="note-preview">
{notePreview.substr(0, 80)}...
</p>
</div>
</li>
Hack incoming! 哈克来了!
I solved this by adding a name
attribute to the elements that I didn't want to trigger the main click event: 我通过向不想触发主点击事件的元素添加
name
属性来解决此问题:
handleClick = (e) => {
if(e.target.name === 'deleteButton') {
e.preventDefault();
e.stopPropagation();
}else {
this.props.selectNote(this.props.note)
}
}
<li className="note" onClick={this.handleClick} role="button">
<button className="delete-note" name="deleteButton" onClick={() => console.log('Fired')}>Delete dis</button>
<span className="updated-at">2hr</span>
<div className="note-content">
<h4 className="note-title">
{title}
</h4>
<p className="note-preview">
{notePreview.substr(0, 80)}...
</p>
</div>
</li>
You need to check which element triggered the event, and prevent it if it was the button. 您需要检查哪个元素触发了事件,如果是按钮,则阻止它。
For Button onClick the default click parameter event args is passed as 'event'. 对于Button onClick,默认的单击参数事件args作为“事件”传递。 Use the event.stopPropagation() to stop propogate the click event back to li.
使用event.stopPropagation()停止将click事件传播回li。
<li className="note" onClick={()=> props.selectNote(props.note)} role="button">
<button className="delete-note" onClick={(event) => event.stopPropagation(); console.log('Fired')}>Delete dis</button>
<span className="updated-at">2hr</span>
<div className="note-content">
<h4 className="note-title">
{title}
</h4>
<p className="note-preview">
{notePreview.substr(0, 80)}...
</p>
</div>
What you need is to prevent further propagation of the current event (click) in the capturing and bubbling phases . 您需要防止在捕获和冒泡阶段进一步传播当前事件(点击)。
See the example on event propagation: https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Examples#Example_5:_Event_Propagation 请参阅事件传播示例: https : //developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Examples#Example_5 : _Event_Propagation
you should wrap your li in a div like below 您应该将li包裹在下面的div中
<div>
<li className="note" onClick={()=> props.selectNote(props.note)} role="button">
<span className="updated-at">2hr</span>
<div className="note-content">
<h4 className="note-title">
{title}
</h4>
<p className="note-preview">
{notePreview.substr(0, 80)}...
</p>
</div>
</li>
<button className="delete-note" onClick={() => console.log('Fired')}>Delete dis </button>
</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.