【问题标题】:Make a button inside an element clickable while the element itself is also clickable使元素内的按钮可点击,同时元素本身也可点击
【发布时间】:2018-07-13 10:02:16
【问题描述】:

我有一个简单的侧边栏,里面有一堆列表项,列表项旁边有一个按钮,如下所示:

我在<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>

但正如预期的那样,当我单击它旁边的按钮时,实际的 li 会被单击,而不是其中的按钮。我认为这是事件如何冒泡的某种问题,以及将onClick 处理程序附加到非交互式元素是一种不好的做法(我的 ESLint 这么说)。

我想要什么

  1. 当列表项被点击时,附加的onClick 事件触发。
  2. 当按钮被点击时,触发按钮上的onClick事件,而不是&lt;li&gt;

【问题讨论】:

    标签: javascript html reactjs dom dom-events


    【解决方案1】:

    黑客入侵!

    我通过向我不想触发主点击事件的元素添加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>
    

    您需要检查哪个元素触发了该事件,如果是按钮则阻止它。

    【讨论】:

    • 这很奇怪,似乎没有一个解决方案有效,即使海报说他们有效。 :c
    • Mine 和 @LivingThing 解决方案都应该可以工作。可能是您的设置中的某些内容。您能否在JSFiddle 中创建一个工作示例,然后我们可以帮助调试?
    • 我刚刚尝试了这两种解决方案,它们都运行良好,我不知道是什么原因造成的......但至少现在它正在运行。谢谢!
    【解决方案2】:
    <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>
    

    【讨论】:

    • data-is-parent 在这种情况下会做什么?
    • 它是一个属性,在 onClick 回调函数中被检查为目标事件属性
    【解决方案3】:

    对于按钮 onClick,默认单击参数事件参数作为“事件”传递。使用 event.stopPropagation() 停止向 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>
    

    【讨论】:

      【解决方案4】:

      你应该将你的 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>
      

      【讨论】:

      • 还是一样。
      【解决方案5】:

      您需要防止在the capturing and bubbling phases 中进一步传播当前事件(点击)。

      查看事件传播示例:https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Examples#Example_5:_Event_Propagation

      【讨论】:

        猜你喜欢
        • 2011-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-03
        • 1970-01-01
        相关资源
        最近更新 更多