Может ли слишком много обработчиков событий повлиять на производительность приложения React? - PullRequest
0 голосов
/ 20 октября 2018

У меня есть 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.Может ли это повлиять на производительность приложения?Если да, то как лучше справиться с таким событием?

Обновление
Как подсказал Алексей, это решение я реализовал:

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()
    }
  }

1 Ответ

0 голосов
/ 20 октября 2018

Комментарий:

Вы можете прикрепить прослушиватель событий при открытии меню и удалить его при закрытии меню.Традиционно это - то, как большинство модалов осуществлено.Только когда модальное окно открыто, вы хотите прослушивать событие click-to-close.

Это может или не может применяться к вашей базе кода, но вы можете также рассмотреть возможность удаления слушателя событияна 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()
  }
}
...