Я создал пользовательский компонент Slider, который отлично работает, за исключением одной проблемы.

Если он присутствует в модале, то для него запускается событие mouseUp для всех событий ниже него (по z-index) перед самим элементом.

Это связано с тем, что для того, чтобы иметь хороший слайдер, вам нужно прикрепить события mouseMove и mouseUp к документу, а не сам слайдер, чтобы вы могли все еще перемещать большой палец и захватывать события мыши, даже когда мышь сдвигается с ползунка при скольжении большого пальца.

В результате теперь у меня возникают проблемы, когда событие mouseUp вызывает события щелчка для элементов, расположенных под ним, до элемента слайдера. Это вызывает проблемы, такие как нажатия кнопок под ним и модальное закрытие (так как они оба являются событиями нажатия).

Потенциальное решение состоит в том, чтобы просто добавить проверки ко всем потенциальным обработчикам событий, которые могут быть перехвачены (что-то вроде if (thisModalOpened) { return false; } для всех других элементов), но это решение кажется немного грязным.

Есть ли лучший способ? Кажется, что способ инвертировать порядок пузырьков может сработать, потому что тогда я мог бы просто вызвать stopPropagation в mouseUp для компонента Slider. Однако я не уверен, что это можно сделать, потому что в настоящее время прослушиватель событий зарегистрирован в документе, так что он может быть обнаружен за пределами самого элемента.

Некоторые фрагменты кода:

componentDidMount() {
  document.addEventListener("pointermove", this.onThumbMove, false);
  document.addEventListener("pointerup", this.onThumbUp, false);
}

onThumbDown = e => {
  this.setState({ dragging: true, startX: this.getX(e) });
}

onThumbMove = e => {
  if (this.state.dragging) {
    this.setState({ position: e.clientX });
  }
}

onThumbUp = e => {
  if (this.state.dragging) {
    let value = this.getValue();

    this.setState({ dragging: false }, () =>
      this.props.onSubmit(value);
    });
  }
}

<div onPointerDown={this.onThumbDown} ref={this.sliderRef}>
  <div>+</div>
</div>

Редактировать: Хорошо, я думаю, что наконец-то понял проблему (но пока не знаю решения): поэтому часто модалы (и мои тоже) имеют окрашенный черный фон, который вы можете нажмите, чтобы легко закрыть модальное окно. Я могу иметь этот черный фон в качестве прямого родителя или родного брата по содержанию модели.

Если он у меня прямой родитель, то я должен вызывать stopPropagation / return false буквально для каждого возможного дочернего компонента, чтобы щелчок по ним не вызывал распространение щелчка вверх и щелчок по фоновому моду и его закрытие , Так что я не хочу это как родитель, потому что это очень хлопотно.

С другой стороны, если он у меня в качестве родного брата, то я не могу вызвать stopPropagation для события document thumbUp, поскольку модальная фоновая маска не является прямым родителем, поэтому она будет зарегистрирована как щелкните и закройте модал, несмотря на вызов stopPropagation, потому что он не является прямым родителем.

В принципе, оба подхода не работают. Я не знаю, как это смириться.

0
Ryan Peschel 18 Дек 2019 в 21:21

1 ответ

Как упомянуто в комментариях @Sarvesh, вы можете добавить третий аргумент в прослушиватель событий, но вместо передачи логического значения вы должны использовать опцию capture для запуска событий сверху вниз, а не снизу вверх, когда вы хотел вот так:

document.addEventListener("pointerup", this.onThumbUp, { capture: true });

Теперь вы можете добавить stopPropagation() в событие mouseUp или в любое другое событие в зависимости от того, что вы хотите.

1
AndrewL64 18 Дек 2019 в 21:42