使用嵌套元素对onClick for disabled按钮进行反应stopPropagation

时间:2017-09-08 11:55:51

标签: javascript reactjs google-chrome

有关此问题和问题的随附示例,请参阅this codepen。相关元数据:

  • react 15.6
  • bootstrap 4.0-beta
  • font-awesome 4.7
  • Firefox v55.0
  • Chrome v60.0

用例

我有一张包含一些数据的表格。用户可以单击一行并编辑行的属性。在每行的一列中,有一个按钮。单击该按钮时,会出现不同的操作和用例。此操作是异步的,用户可以获得有关此异步操作的反馈 单击按钮是一个不同的操作,而不是单击按钮边框外部(因此单击'')。

代码示例

class App extends React.Component {
  constructor(props){
    super(props);

    this.state = {
      isDeleting: false
    };

    this.handleRowClick = this.handleRowClick.bind(this);
    this.handleButtonClick = this.handleButtonClick.bind(this);
  }

  handleRowClick(event) {
    alert("you clicked the row [use case 1]");
  }

  handleButtonClick(event){
    event.stopPropagation();
    this.setState({isDeleting: true});
    alert("you clicked the button [use case 2]");
  }

  render() {
    return (
      <table className="table">
        <thead>
          <tr>
            <th>Header 1</th>
            <th>Header 2</th>
            <th></th>
          </tr>
        </thead>
        <tbody>
          <tr onClick={this.handleRowClick}>
            <td>Data 1</td>
            <td>Data 2</td>
            <td>
              <button disabled={this.state.isDeleting}
                      className="btn btn-outline-danger btn-sm p-5"
                      type="button"
                      onClick={this.handleButtonClick}>
                {
                  this.state.isDeleting
                  ? <span><i className="fa fa-spinner fa-pulse"/> Deleting</span>
                    : "Delete"
                }

              </button>
            </td>
          </tr>
        </tbody>
      </table>
    );
  }
}

问题

在上面的代码示例中,您可以看到无论何时单击该按钮,该按钮都会被禁用(实际上是,在异步操作完成之前它被禁用)。在示例中,按钮被永久禁用以证明该点 当您使用Firefox在codepen中尝试此操作时,UI的行为与预期一致。如果您在禁用按钮时尝试单击该按钮,则不会发生任何事情:这是所需效果。
但是,当您使用Chrome尝试此操作时,会发生不良影响。首先单击该按钮,然后在禁用该按钮时,单击加载图标(<i>元素)或包含在Deleting元素内的文本<span>。您可以看到handleRowClick被调用(此 问题)。有一个原因我在示例中使填充如此巨大,因为如果您在<span>元素的边框外单击,但仍然在<button>的边界内,则没有任何反应(其中最终是期望的效果,因为它被禁用了。)

问题

因此浏览器之间显然不一致,这对开发人员来说很烦人。 Firefox似乎尊重开发人员的隐含假设。这会是Chrome问题吗?或者也许是React中的错误?在任何情况下,我们的客户都不能等到任何一个人解决这个问题,因此需要一个有效的解决方案,同时仍然尊重客户的愿望。有没有其他人以前遇到过这个问题,如果有,那么最好的解决方案是什么? 我能想到的唯一解决方案是我不愿意应用的解决方案:
检查event.target回调中的handleRowClick。然而,这增加了潜在的可维护性问题如果其中一个列具有嵌套元素,则需要添加其他逻辑以检查所点击的内容。

1 个答案:

答案 0 :(得分:3)

点击后,您的按钮被停用,因此onClick归因于内部span

将以下CSS样式添加到子元素

pointer-events: none;

有关工作示例,请参阅this codepen