Компонент выбора игнорирует родительское событие onClick

Проблема:

У меня есть событие щелчка, которое является частью поведения родительского компонента, но при непосредственном выборе компонента или этот onClick игнорируется, и я не смог понять, почему события имеют приоритет.

Я пробовал несколько уровней e.stopPropagation () и e.preventDefault () как для родительского, так и для дочернего, но безуспешно.

Это для веб-сайта, отображаемого на мобильных устройствах

Это упрощенная версия моей проблемы

<div onClick={()=>console.log('Print Something')}>
    <div className='containerStyles' >
        <Select autofocus={false}>
    </div>
</div>

Если я нажму на заполнение «containerStyles» или за его пределами, консоль что-то напечатает, потому что запускается onClick.

Однако, если я нажимаю на компонент «Выбрать» напрямую, в консоли ничего не печатается.

Что нужно:

Мне нужно руководство по приоритетам событий и как я могу заставить console.log печатать сообщение при нажатии на что-нибудь внутри него. Даже если выбор будет сфокусирован, мне просто нужно убедиться, что родительский onClick также выполняется.


person Elkdor    schedule 16.08.2019    source источник
comment
Я не понимаю такого поведения, для меня это работает, как и следовало ожидать. Я не знаю, может ли это быть связано с опечаткой autofocus, но я сомневаюсь в этом ... Вы говорите, что это упрощенная версия. Возможно, неупрощенная версия прольет свет.   -  person silencedogood    schedule 16.08.2019
comment
Я согласен. Текущий код (вне опечатки) должен работать. Можете ли вы воспроизвести эту проблему в codeandbox, чтобы мы увидели?   -  person technicallynick    schedule 16.08.2019
comment
Это codeandbox Я тоже редактировал вопрос. Я забыл упомянуть, что это используется в мобильном браузере. Используя информацию, которую я получил от user9408899, мне удалось выяснить, что для ‹Select› в мобильных браузерах используется событие onTouchEnd, а не onClick ... Что-то должно измениться между ними, я думаю, что onClick вызывает stopPropagation() в какой-то момент для мобильных ? решение для меня в конечном итоге заключалось в том, чтобы использовать onTouchEnd () вместо onClick () и каким-то образом это исправить ...   -  person Elkdor    schedule 16.08.2019


Ответы (1)


Мне нужно руководство по приоритетам событий

1. Ванильный футляр

Click event будет передаваться от дочернего к родительскому, это поведение по умолчанию.

Следующие примеры демонстрируют это поведение. Событие родительского щелчка будет запущено, даже если вы щелкнете дочерний элемент.

function App() {
  return (
    <div className="App">
      <div className="box1" onClick={() => console.log("parent")}>
        <div className="box2" />
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render( < App / > , rootElement);
.App {
  font-family: sans-serif;
  text-align: center;
  display: flex;
}

.box1 {
  background-color: red;
  width: 200px;
  height: 200px;
}

.box2 {
  background-color: black;
  width: 100px;
  height: 100px;
  margin: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root" />


2. stopPropagation (отступы и границы)

Если вы хотите заблокировать поведение по умолчанию, вам нужно использовать функцию e.stopPropagation. Я добавил отступы и границу к дочернему элементу, чтобы проиллюстрировать условия, в которых работает stopPropagation.

Даже если вы щелкнете границы или отступы, распространение будет заблокировано функцией stopProgation.

function App() {
  return (
    <div className="App">
      <div
        className="box1"
        onClick={e => {
          console.log("parent");
          e.stopPropagation();
        }}
      >
        <div
          className="box2"
          onClick={e => {
            console.log("child");
            e.stopPropagation();
          }}
        />
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.App {
  font-family: sans-serif;
  text-align: center;
  display: flex;
}

.box1 {
  background-color: red;
  width: 200px;
  height: 200px;
}
.box2 {
  background-color: black;
  width: 100px;
  height: 100px;
  margin: auto;
  padding: 15px;
  border: 7px solid yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />


Даже если выбор будет сфокусирован, мне просто нужно убедиться, что родительский onClick также выполняется.

Если click event не распространяется, убедитесь, что компонент Select не имеет функции stopPropagation.

В худшем случае определите функцию в родительском компоненте и передайте ее в качестве свойства дочернему компоненту. Затем вызовите эту функцию при событии onClick в дочернем компоненте.

person user9408899    schedule 16.08.2019
comment
Спасибо за информацию, именно поэтому я хотел подтвердить ... Я действительно попытался создать codeandbox, и там элементы работают, поэтому я буду продолжать пытаться увидеть, какие другие элементы в моем коде мешают, и опубликовать Обновить. - person Elkdor; 16.08.2019
comment
Используя ваше руководство, мне удалось найти решение, которое сработало для меня. событие, которое мне нужно было использовать, было onTouchEnd, а не onClick. Я думаю, что компонент ‹Select› обрабатывает stopPropagation по-разному для обоих ... и, поскольку мое приложение предназначено для мобильного браузера, onTouchEnd сработало. - person Elkdor; 16.08.2019