太多的事件处理程序会影响 React 应用程序的性能吗?

Can too many event handlers impact the performance of a React-app?

我有一个 Toggler button 可以打开下拉菜单。要添加一项功能,如果用户单击该菜单以外的屏幕上的任何地方,下拉菜单应该关闭。因此,为此,我需要创建点击处理程序并保留发生点击的节点的记录。如果点击来自下拉节点之外,菜单应该关闭。这是代码:

  state = {
    menuTogglerOpen: false
  }

  componentWillMount() {
    document.addEventListener("mousedown", this.handleClick, false)
  }
  componentWillUnmount() {
    document.removeEventListener("mousedown", this.handleClick, false)
  }

  handleClick = event => {
    if (this.togglerNode.contains(event.target)) {
      return
    }
    this.closeMenuTogglerFromOutside()
  }

  closeMenuTogglerFromOutside = () => {
    this.setState({
      menuTogglerOpen: false
    })
  }

  handleMenuToggler = () => {
    this.setState({
      menuTogglerOpen: !this.state.menuTogglerOpen
    })
  }

JSX

<Toggler ref={currentNode=> (this.togglerNode = currentNode)}>
  <button onClick={this.handleMenuToggler}>
                <svg
                  ...button SVG...
                </svg>
              </button>
  {this.state.menuTogglerOpen && (
  <TogglerDropDown>
    <div className="_dropdown_caret" />
    <div className="_dropdown">
      <ul>
        <li>puspender</li>
        <li>settings</li>
        <li>help</li>
        <li>logout</li>
      </ul>
    </div>
  </TogglerDropDown>
  )}
</Toggler>
</HeaderGroup>
</SiteHeaderRight>   

在这种方法中,每次点击(屏幕上的任何地方)都会调用 handleClick 方法。它会影响应用程序性能吗?如果是,处理此类事件的更好方法是什么?

更新
正如 Alexei 所建议的,这是我实施的解决方案:

handleClick = event => {
    if (this.togglerNode.contains(event.target)) {
      return
    }
    this.closeMenuToggler()
  }

  openMenuToggler = () => {
    document.addEventListener("mousedown", this.handleClick, false)
    this.setState({
      menuTogglerOpen: true
    })
  }

  closeMenuToggler = () => {
    document.removeEventListener("mousedown", this.handleClick, false)
    this.setState({
      menuTogglerOpen: false
    })
  }

  handleMenuToggler = () => {
    if (this.state.menuTogglerOpen) {
      this.closeMenuToggler()
    } else {
      this.openMenuToggler()
    }
  }

评论:

You could attach the event listener when the menu opens, and remove it when the menu closes. Traditionally that's how most modals are implemented. Only when the modal is open do you want to listen for the click-to-close event.

这可能适用于也可能不适用于您的代码库,但您可能还需要考虑删除 componentWillUnmount 上的事件侦听器,这样可以避免任何潜在的内存泄漏。这涵盖了组件卸载而不调用 closeMenuToggler 的情况,在这种情况下,您将离开陈旧的事件侦听器 运行.

componentWillUnMount() {
  if (this.state.menuTogglerOpen) {
    document.removeEventListener("mousedown", this.handleClick, false)
  }
}

handleClick = event => {
  if (this.togglerNode.contains(event.target)) {
    return
  }
  this.closeMenuToggler()
}

openMenuToggler = () => {
  document.addEventListener("mousedown", this.handleClick, false)
  this.setState({
    menuTogglerOpen: true
  })
}

closeMenuToggler = () => {
  document.removeEventListener("mousedown", this.handleClick, false)
  this.setState({
    menuTogglerOpen: false
  })
}

handleMenuToggler = () => {
  if (this.state.menuTogglerOpen) {
    this.closeMenuToggler()
  } else {
    this.openMenuToggler()
  }
}