Вызовите event.preventDefault () после вызова event.persist () в React - PullRequest
1 голос
/ 03 мая 2019

Я исследовал синтетические события в React и понимаю, что React объединяет события для повышения производительности. Я также знаю, что события в React не являются событиями DOM. Я прочитал несколько сообщений и тем на эту тему, но не могу найти упоминания о звонке preventDefault после звонка event.persist.

Многие сайты упоминали, что, например, если мы хотим зафиксировать значение event.target, один из вариантов - просто кэшировать его для последующего использования, но это не относится к моему случаю использования.

Я хочу ограничить обработчик событий, который прослушивает onDragOver события. Чтобы сделать это в React, я должен передать событие через 3 функции, вызывая event.persist для первой, чтобы последняя могла его увидеть.

Однако, event.preventDefault не имеет никакого эффекта, когда я это называю. Это почти как если бы мы позвонили event.persist, вот и все, и нет пути назад.

Ниже приведен фрагмент кода, но вам может быть полезно поэкспериментировать с ним на StackBlitz .

import React, { Component } from 'react';
import { throttle } from 'throttle-debounce';
import DropItem from './DropItem';

class DropZone extends Component {
  constructor(props) {
    super(props);
    this.onDragOverThrottled = throttle(500, this.onDragOver);
    this.onDragStart = this.onDragStart.bind(this);
    this.handleDragOver = this.handleDragOver.bind(this);
  }

  onDragStart(e, id) {
    console.log('dragstart: ', id);
    e.dataTransfer.setData("id", id);
  }

  onDragOver(e) {
    e.preventDefault();  // this does nothing if event.persist fires before it
    console.log('dragover...');
  }

  handleDragOver(e) {
    e.persist();
    this.onDragOverThrottled(e);
  }

  render() {
    const items = this.props.items.map((item, index) => {
      return <DropItem item={item} key={index} onDragStart={this.onDragStart} />;
    });

    return (
      <div
        className={this.props.class}
        //onDragOver={this.handleDragOver}  // See note 1 below
        onDragOver={this.onDragOver}  // See note 2 below
        onDrop={(e) => {this.props.onDrop(e, this.props.location)}}>
        <span className="task-header">{this.props.title}</span>
        {items}
      </div>
    );
  }
}

export default DropZone;

/*

NOTE 1
Commenting in this line shows that throttling works but preventDefault does not and we cannot drag and drop any box to another location.

NOTE 2
This skips throttling altogether but preventDefault does work which allows the box to be moved to a different area. Because throttling is disabled here, onDragOver fires a lot and, at times, keeps the user from moving boxes around quickly.

*/

Все источники, с которыми я консультировался, эффективно реализовали либо debounce, либо throttle для захвата значения, а затем что-то сделали с этим значением, но ни один из них не пытался вызвать preventDefault после persist, как я пытаюсь сделать. Вот некоторые из этих источников:

  • Блог Пост о троттлинге и глушении
  • Пример регулирования входа peterbe
  • A скрипка , которая делает именно то, к чему я стремлюсь, но это не написано в React

1 Ответ

0 голосов
/ 04 мая 2019

После дальнейших исследований и экспериментов я выяснил, как решить эту проблему.

TL; DR
Моя теория о том, что event.persist() каким-то образом мешала event.preventDefault() работать как положенобыло неверно.

РЕАЛЬНАЯ ПРОБЛЕМА
Причина, по которой мое приложение перетаскивания не работало с регулированием, было из-за того, что event.persist() не перенаправляет событие другому обработчику, нопросто делает его доступным для других обработчиков.Это означает, что event.preventDefault() должен вызываться для каждого обработчика, который использует событие.Теперь, когда я это говорю, это кажется очевидным, но поскольку мне пришлось отправить событие через несколько обработчиков для реализации регулирования, я ошибочно подумал, что передаю событие от одного к другому.

ДОКУМЕНТАЦИЯ
То, что я заявляю выше, является моим наблюдением и не основано на официальной документации React.Но React docs действительно говорят это:

Если вы хотите получить доступ к свойствам события асинхронным способом, вы должны вызвать event.persist() для события, которое удалитсинтетическое событие из пула и возможность сохранения ссылок на событие в пользовательском коде.

Несмотря на то, что я читал это раньше, я пропустил его, потому что не считал то, что делал, асинхронным,Но ответ все еще здесь - он позволяет сохранять ссылки на событие с помощью кода пользователя .

УЗНАТЬ БОЛЬШЕ
Для тех, кто хочет копаться вглубже, обязательно посмотрите на README в моем StackBlitz, где я предоставлю дополнительную информацию.

...