Bootstrap Пользовательский стиль флажок вызывает событие нажатия дважды - PullRequest
0 голосов
/ 11 февраля 2020

При использовании Bootstrap с React дважды запускается событие нажатия кнопки в пользовательском стиле. Один для rowClicked и другой для checkboxClicked. Это происходит только тогда, когда я использую bootstrap пользовательский стиль флажок. Флажок по умолчанию не имеет этой проблемы.

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

Пример: https://codepen.io/my-sandbox-online/pen/OJVVdOB

Код :

class Test extends React.Component {
   constructor(props) {
    super(props);
    this.checkboxClicked = this.checkboxClicked.bind(this);
    this.rowClicked = this.rowClicked.bind(this);
   }

  checkboxClicked (e) {
    e.stopPropagation();
    console.log('clicked on checkbox');
  }

  rowClicked (e) {
    console.log('clicked on row');
  }

  render() {
    return (
      <div className="container">
        <table className="table">
          <thead>
            <tr>
              <th>&nbsp;</th>
              <th>Names</th>
            </tr>
          </thead>
          <tbody>
            <tr onClick={(e) => this.rowClicked(e)}>
              <td>
              <div className="custom-control custom-checkbox my-1 mr-sm-2">
                <input type="checkbox" className="custom-control-input" id="test"
                onClick={(e) => this.checkboxClicked(e)}
                />
                <label className="custom-control-label" htmlFor="test"></label>
              </div>
              </td>
              <td>Row 1</td>
            </tr>

            <tr onClick={(e) => this.rowClicked(e)}>
              <td><input type="checkbox" onClick={(e) => this.checkboxClicked(e)} /></td>
              <td>Row 2</td>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
}

ReactDOM.render(
  <Test />,
  document.getElementById('root')
);

Ответы [ 2 ]

0 голосов
/ 11 февраля 2020

Эта ошибка возникает из-за того, что если мы используем bootstrap пользовательский флажок в стиле, фактический флажок, который вы видите на экране, не является:

<input type="checkbox" className="custom-control-input" id="test"
            onClick={(e) => this.checkboxClicked(e)}

, но его флажок javascript сделан (я думаю, что он сделан из div) ... и, следовательно, когда вы устанавливаете флажок, сначала будет активирован щелчок строки ... и затем javascript, принадлежащий bootstrap, вызовет исходное событие флажка checkbox, и будет вызван checkboxClicked.

в то время как на исходном флажке без собственного стиля boostrap, оно вызовет исходное событие флажка checkbox, и будет вызван checkboxClicked.

для решения, может быть, мы должны удалить событие rowclick, это не очень хорошая идея поместить click в строку, где у другого дочернего элемента есть событие click, например, поместить ссылку внутри ссылки, которая не будет работать с обычным HTML.

, или другим способом, если вы настаиваете на установке события rowclick, может будь мы можем использовать e.target.type или мы можем использовать данные - и делать проверку.

0 голосов
/ 11 февраля 2020

Ответ и немного объяснений:

  1. <input type="checkbox" className="custom-control-input" id="test"/> скрыт, поэтому мы фактически нажимаем на label
  2. , когда обрабатываем щелчок на скрытом флажке - там невозможно перехватить его до того, как row обработает событие, поэтому
  3. onClick перемещается из checkbox в label, чтобы обработать события до row.
  4. Я не очень знаком с реакцией, поэтому я не знаю лучшего способа подавления события, чем, e.preventDefault(); e.stopPropagation(); e.nativeEvent.stopImmediatePropagation();
  5. событие подавлено, и теперь row больше не участвует, к сожалению, также checkbox. это значение не обновляется, потому что мы подавили распространение события.
  6. , проверяя, является ли цель события label, выбирая цель метки и переключая значение.
  7. прибыль)

Рабочий пример:

class Test extends React.Component {
   constructor(props) {
    super(props);
    this.checkboxClicked = this.checkboxClicked.bind(this);
    this.rowClicked = this.rowClicked.bind(this);
   }

  checkboxClicked (e) {
    e.preventDefault()
    e.stopPropagation();
    e.nativeEvent.stopImmediatePropagation();
    if (e.target.tagName === 'LABEL') {
      const checkbox = document.querySelector(`#${e.target.htmlFor}`);
      if (checkbox) {
        checkbox.checked = !checkbox.checked;
      }
    }

    console.log('clicked on checkbox');
  }

  rowClicked (e) {
    console.log('clicked on row');
  }

  render() {
    return (
      <div className="container">
        <table className="table">
          <thead>
            <tr>
              <th>&nbsp;</th>
              <th>Names</th>
            </tr>
          </thead>
          <tbody>
            <tr onClick={(e) => this.rowClicked(e)}>
              <td>
              <div className="custom-control custom-checkbox my-1 mr-sm-2">
                <input type="checkbox" className="custom-control-input" id="test"
                />
                <label onClick={(e) => this.checkboxClicked(e)} className="custom-control-label" htmlFor="test"></label>
              </div>
              </td>
              <td>Row 1</td>
            </tr>

            <tr onClick={(e) => this.rowClicked(e)}>
              <td><input type="checkbox" onClick={(e) => this.checkboxClicked(e)} /></td>
              <td>Row 2</td>
            </tr>
          </tbody>
        </table>
      </div>
    );
  }
}

ReactDOM.render(
  <Test />,
  document.getElementById('root')
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...