【问题标题】:Clicking on a div that contains span, doesn't trigger onclick event - React单击包含跨度的 div,不会触发 onclick 事件 - React
【发布时间】:2019-05-14 20:47:53
【问题描述】:

我有一个 div,在里面我根据某些条件渲染 span。如果组件有一些孩子,我希望这个 div 扩展。如果我在内部跨度之外的区域上单击此 div,它工作正常。

一个例子,是下面的Image。单击该行时,它会扩展区域以显示诸如this 之类的项目。但是,当我单击标题文本时,它不起作用,单击事件不会触发。

这是我的代码:

 <div className={headerStyles.header} onClick={(e) => this.selectHeader(e, this.props.items.length)}>
    {this.props.items.length > 0 && 
          <span className={headerStyles.expand} style={{ color: this.props.headerNameColor }}></span>
                    }
          <span style={{ color: this.props.headerNameColor }}  >{this.props.headerName}</span>
                    {this.props.headerUrl &&
                        <a
                            style={{ color: this.props.headerNameColor }}
                            href={this.props.headerUrl}
                            data-interception="off"
                            target="_blank"
                            title="Open link in a new tab">
                            <i className={['ms-Icon', 'ms-Icon--OpenInNewWindow', headerStyles.openNewTab].join(' ')}></i>
                        </a>
                    }
                </div>

这是点击标题时调用的函数:

 selectHeader(e, numOfItems) {
        if (e.target.children.length > 0 && numOfItems > 0) {
            e.target.children[0].classList.toggle(headerStyles.expand)
            e.target.children[0].classList.toggle(headerStyles.collapse)
            e.target.parentElement.querySelector(`.${headerStyles.items}`).classList.toggle(headerStyles.hidden)
        }
        else if(this.props.headerUrl){

        }
    }

感谢任何指导。

谢谢

【问题讨论】:

  • 函数this.selectHeader是什么样的?事件目标将根据您单击的内部元素而有所不同,如果您将该事件传递给不同的函数,则需要小心处理。
  • 嗨@jered,请查看我更新的帖子。

标签: javascript css reactjs


【解决方案1】:

正如我所怀疑的,您正试图对 selectHeader 中的 event.target 值做一些事情。这不会很好地工作,因为event.target 会根据您在 div 中单击的元素而改变。它并不总是外部的“父”元素。

您还尝试从 DOM 强制读取数据,这不是一种非常“React”的做事方式。事实上,在您的函数中,您正在执行 classList.toggle(headerStyles.hidden),这与 React 管理应用程序的状态和呈现直接冲突。你需要的所有数据都应该存在于你的 React 应用程序的状态中——你根本不需要查询 DOM。

抛弃 event.targetclassList.toggle 并找到使用 React 状态的方法。例如,当您单击 div 时,您可以简单地切换组件的“展开”状态,并使用该状态来确定要呈现的 CSS 类:

<div onClick={() => {this.setState({isExpanded: !this.state.isExpanded})}} >
  <span className={this.state.isExpanded ? headerStyles.expand : headerStyles.collapse} ></span>
</div>

【讨论】:

  • 毕竟是 CSS 问题。感谢您的帮助。
  • @Dan 我考虑了另一个答案并特别省略了它,因为它的运行与 React 的预期使用方式直接相反,并且可能会在以后引起许多奇怪的问题。请重新考虑。
  • 谢谢@jered。我在父 div 本身上绑定 .click 事件,而不是在任何子元素上。所以函数 selectedHeader 只会在单击 div 时触发,并且 e 将始终引用 div。对吗?
  • 我完全同意 classList.toggle,但它不是一种反应方式,我应该改变它。
【解决方案2】:

尝试将pointerEvents: 'none' 样式添加到span 标签,这样它就不会收到任何鼠标事件。这将使event.target 始终是div

【讨论】:

  • 太棒了。谢谢。由于没有足够的代表,我无法投票赞成您的回复。!​​
  • 我很抱歉,但我认为这是针对这种情况的糟糕建议。它提倡对 React 应该如何操作的完整解决方法。使用 event.targetclassList.toggle 在 React 之外强制修改 DOM 是一种讨厌的习惯,只会在以后引起问题。我在自己的回答中考虑了这个解决方案,并明确省略了它,因为它有多大问题。
【解决方案3】:

这里避免在 JSX 中使用箭头函数。 e 对象总是被传递,因为这是一个事件处理程序,并且您的 props 可以从您的处理程序访问:

selectHeader = (e) => {
     const numOfItems = this.props.items.length;
     // rest of the code...

 }

内部渲染方法:

&lt;div onClick={this.selectHeader}&gt;

【讨论】:

  • 没有任何区别,展开/折叠仍然有效,但点击标题时无效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-21
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 2014-09-18
相关资源
最近更新 更多