【问题标题】:Passing only clicked element to onClick function - reactjs仅将单击的元素传递给 onClick 函数 - reactjs
【发布时间】:2017-10-20 21:09:52
【问题描述】:

我有多个具有相同 className 的元素,如果单击某个元素(带有 className history-node),我希望它应该获得 className active 连同当前的类名。

但我遇到了一个问题,该元素有子元素,如果单击子元素,它们也会获得类 Active

代码如下:

<div className="history-node-container" key={index}>
  <div className="history-node" onClick={(e) => {this.handleHistoryClick(e.target)}}>
    <span className="history-title">{heading.action}</span>
    <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span>
  </div>
</div>

handleHistoryClick函数

handleHistoryClick(target){
  $('.history-node').removeClass('active'); //removing active class from all elements
  target.className = 'history-node active';
}

我想在用户单击类名 history-node

的元素时运行函数

但如果用户点击 history-title,ClickHandler 会将 active 类赋予 history-title 元素。

预期行为:如果单击历史节点,则只有历史节点应该获得类 active

【问题讨论】:

    标签: javascript jquery reactjs


    【解决方案1】:

    一个提示以及如何解决您的问题(两种方式)

    提示:将ReactjQuery 混合通常不是最好的主意。 React 的出现是我们与DOM 交互方式的重大范式转变。尝试阅读更多关于 React 的内容,它是如何工作的,为什么它与使用 jQ 在DOM 中简单地添加/删除元素如此不同。

    一些参考资料可以帮助您:

    How to go from jQuery to React.js?

    Thinking in React for jQuery Programmers


    现在,回到你的问题

    你应该使用currentTarget

    由于.history-title.history-date 元素被包裹在.history-node 中,任何点击它们都会触发它的父事件,因为.history-node 正文是.history-title + .history-date。这是正确的行为。当你在 JS 中触发事件时,event 对象接收两个参数:target 是触发事件的事件,currentTarget 是实际监听事件的元素。

    现在是代码:

    与 JQ

    组件:

    <div className="history-node-container" key={index}>
      <div className="history-node" onClick={handleHistoryClick}>
        <span className="history-title">{heading.action}</span>
        <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span>
      </div>
    </div>
    

    点击:

    handleHistoryClick(event){
      $('.history-node').removeClass('active')
      event.currentTarget.classList.add('active')
    }
    

    React 方式(纯 React,无模块)

    组件:

    class HistoryNode extends Component {
        constructor(props) {
            super(props)
            this.state = { isActive: false }
            this.handleClick = this.handleClick.bind(this)
        }
    
        handleClick(e) {
          let state = this.state
          this.setState({isActive: !state.isActive})
        }
    
        render() {
          return(
            <div className="history-node-container">
              <div className={`history-node ${this.state.isActive ? 'active' : ''}`} onClick={handleHistoryClick}>
                <span className="history-title">{heading.action}</span>
                <span className="history-date">
                   {moment(heading.added_at).format("MMMM Do, YYYY")}</span>
              </div>
            </div>
          )
        }
    }
    

    请注意,在 React 解决方案中,您无需随时操作 DOM。您只需将您的事件附加到该特定组件,定义它的状态更改应如何反映在 UI 上,然后让 React 完成其余的工作。

    希望对你有帮助;)

    Reference for target vs currentTarget

    【讨论】:

    • 很好的解释。非常感谢您的时间和精力。我得到了它的工作。
    【解决方案2】:

    我认为事件会传播到子组件。

    你试过了吗?

    <div className="history-node-container" key={index}>
      <div className="history-node" onClick={handleHistoryClick}>
        <span className="history-title">{heading.action}</span>
        <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span>
      </div>
    </div>
    

    手柄点击功能

    handleHistoryClick(event){
      event.stopPropagation();
      $('.history-node').removeClass('active');
      event.target.className = 'history-node active';
    }
    

    编辑:您可以使用您的组件状态使其更简单(并且没有 jQuery)。但是在不知道你是如何编写组件的情况下,我无法给你一个 sn-p 来说明它。直接与 DOM 交互时也要小心,这意味着性能损失。使用 React 状态可以避免这样的事情!

    【讨论】:

    • 你能用整个组件编辑你的原始帖子吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 2013-11-28
    • 2020-12-23
    • 2023-01-08
    • 2011-07-15
    相关资源
    最近更新 更多