在React

时间:2019-05-03 19:23:10

标签: javascript reactjs performance dom-events

我在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.

*/

我咨询过的所有资源都有效地实现了反跳或限制以捕获值,然后对该值进行处理,但是没有一个人像我一样尝试在preventDefault之后调用persist尝试做。其中一些来源如下:

  • post上进行节流和反跳博客
  • 通过peterbe限制输入的示例
  • 一个完全符合我的目标的fiddle,但它不是用React编写的

1 个答案:

答案 0 :(得分:0)

经过进一步的研究和实验,我找到了解决方法。

TL; DR
我的event.persist()某种程度上阻止event.preventDefault()正常工作的理论是错误的。

真正的问题
我的拖放应用程序无法进行节流的原因是,event.persist()不会将事件转发给另一个处理程序,而只是让其他处理程序可以访问它。这意味着必须在使用该事件的每个处理程序上调用event.preventDefault()。现在我说了这似乎很明显,但是因为我必须通过多个处理程序发送事件以实现限制,所以我错误地认为我是将事件从一个传递到另一个。

文档
我上面所说的只是我的观察,并非来自React的官方文档。但是React docs确实这么说:

  

如果要以异步方式访问事件属性,则可以   应该在事件上致电event.persist(),这将删除   池中的合成事件,并允许对该事件的引用为   由用户代码保留。

尽管我之前已经读过这篇文章,但由于我不认为自己正在做异步操作,所以我跳过了它。但是答案仍然在这里-它允许用户代码保留对该事件的引用

了解更多信息
对于那些想深入研究的人,请务必查看我的StackBlitz中的README,在其中我会提供更多详细信息。