我在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
尝试做。其中一些来源如下:
答案 0 :(得分:0)
经过进一步的研究和实验,我找到了解决方法。
TL; DR
我的event.persist()
某种程度上阻止event.preventDefault()
正常工作的理论是错误的。
真正的问题
我的拖放应用程序无法进行节流的原因是,event.persist()
不会将事件转发给另一个处理程序,而只是让其他处理程序可以访问它。这意味着必须在使用该事件的每个处理程序上调用event.preventDefault()
。现在我说了这似乎很明显,但是因为我必须通过多个处理程序发送事件以实现限制,所以我错误地认为我是将事件从一个传递到另一个。
文档
我上面所说的只是我的观察,并非来自React的官方文档。但是React docs确实这么说:
如果要以异步方式访问事件属性,则可以 应该在事件上致电
event.persist()
,这将删除 池中的合成事件,并允许对该事件的引用为 由用户代码保留。
尽管我之前已经读过这篇文章,但由于我不认为自己正在做异步操作,所以我跳过了它。但是答案仍然在这里-它允许用户代码保留对该事件的引用。
了解更多信息
对于那些想深入研究的人,请务必查看我的StackBlitz中的README,在其中我会提供更多详细信息。