我有一个div,如果光标悬停在div上,它应该显示为“ HOVERING”,否则显示为“ NOT HOVERING”。由于某种原因,如果我慢慢将鼠标悬停在页面上的每个div上,它的行为就会与预期的一样;但是,如果我在屏幕上快速移动光标,则某些div会切换。意思是,当我的光标移到div上方时,它们将显示“ NOT HOVERING”;当我的光标不在div上时,它们将显示“ HOVERING”。
Chrome和Safari中均会发生此错误。
沙箱:
https://codesandbox.io/s/aged-butterfly-r2g6x?file=/src/Geo.js
将光标快速移到各个框上以查看问题。
答案 0 :(得分:1)
我认为您的实现的主要问题在于异步事件回调在event loop中排队和处理的方式。我找不到有关处理事件回调的延迟的任何硬性详细信息,但是如果您想进行深入研究,文档here和here可能会为您提供更多信息。
基本上,这个问题有两个方面:
将鼠标移动事件侦听器添加到窗口对象,并检查鼠标移动事件目标是否包含在您的元素之一中。如果当前未悬停并且元素包含事件目标,则将isHovered
设置为true;如果当前已悬停并且元素不包含事件目标,则将isHovered
设置为false。
这不能完全替代附加到包含的div
上的enter / leave | over / out事件侦听器,因为我仍然能够重制边缘情况。我注意到当快速移动鼠标并离开窗口时,您的UI最容易受到此问题的影响。
将window和div事件侦听器组合在一起可以提供很好的解析度(尽管我仍然能够重现边缘情况,这很难做到)。似乎也有所帮助的是没有为div定义匿名回调函数。
import React, { createRef } from "react";
export default class Geo extends React.Component {
state = {
isHovering: false
};
mouseMoveRef = createRef();
componentDidMount() {
window.addEventListener("mousemove", this.checkHover, true);
}
componentWillUnmount() {
window.removeEventListener("mousemove", this.checkHover, true);
}
setHover = () => this.setState({ isHovering: true });
setUnhover = () => this.setState({ isHovering: false });
checkHover = e => {
if (this.mouseMoveRef.current) {
const { isHovering } = this.state;
const mouseOver = this.mouseMoveRef.current.contains(e.target);
if (!isHovering && mouseOver) {
this.setHover();
}
if (isHovering && !mouseOver) {
this.setUnhover();
}
}
};
render() {
var textDisplay;
if (this.state.isHovering) {
textDisplay = <span>HOVERING</span>;
} else {
textDisplay = <h1>NOT HOVERING</h1>;
}
return (
<div
ref={this.mouseMoveRef}
onMouseEnter={this.setHover}
onMouseLeave={this.setUnhover}
style={{ width: 300, height: 100, background: "green" }}
>
{textDisplay}
</div>
);
}
}
答案 1 :(得分:0)
据我所知,您更新状态的方式存在问题。请记住,React可以异步更新状态。
更改toggleHoverState函数将解决此问题
lst_a = ['it is an', 'example of', 'an english simple sentence', 'if time permits', 'I will learn', 'this weekend', 'but do not', 'count on me']
lst_b = ['It', 'is', 'an', 'example', 'of', 'an', 'english', 'simple', 'sentence.', 'If', 'time', 'permits,', 'I', 'will', 'learn', 'this', 'weekend', 'but', 'do', 'not', 'count', 'on', 'me']
lst_c = ['It is an', 'example of', 'an english simple sentence.', 'If time permits,', 'I will learn', 'this weekend', 'but do not', 'count on me']
转到this section in React docs了解更多信息