首页 > 解决方案 > 检查延迟后元素是否仍有 mouseenter

问题描述

我用 amouseentermouseleave

<button onMouseEnter={this.MouseEnter}>hover</button>

MouseEnter(e) {
    setTimeout(() => {
        //check if mouse over still on this element 
        // do action
    }, 600);
}

问题是当我快速移动块时,最后一个块在超时之前检测到 mouseenter 并执行操作,即使我没有悬停在块上,这是一个错误,我想让它只在500ms悬停后运行在块上。

ps:我正在使用 react.js

标签: javascriptreactjsmouseevent

解决方案


如果事件被触发,您真正缺少的是超时回调的失效。mouseLeave为此,您需要保留返回setTimeout值以便clearTimeout在计时器到期之前调用(或者如果组件卸载!!

以下是基于类的组件中的基本机制:

state = {
  hovered: false
};
timer;

mouseEnterHandler = () => this.setState({ hovered: true });
mouseLeaveHandler = () => this.setState({ hovered: false });

onTimeout = () => {
  // Do action
};

clearTimer = () => {
  clearTimeout(this.timer);
};

// Here's the meat:
// If state updates, then componentDidUpdate is called,
// if the new hovered state is true, set timeout and save the
// returned reference, else clear the timeout using the saved
// timer reference.

componentDidUpdate() {
  const { hovered } = this.state;

  if (hovered) {
    this.timer = setTimeout(this.onTimeout, 500);
  } else {
    this.clearTimer();
  }
}

// This is component cleanup, if the component unmounts before
// the timer expires you may not want the "Do action" to fire,
// so we go ahead and clear the timeout so you're not accidentally
// accessing state/props of an unmounted component.

componentWillUnmount() {
  this.clearTimer();
}

以下是等效的功能组件逻辑:

const [hovered, sethovered] = useState(false);

const mouseEnterHandler = () => sethovered(true);
const mouseLeaveHandler = () => sethovered(false);

const onTimeout = () => {
  // Do action
};

useEffect(() => {
  const timer = hovered && setTimeout(onTimeout, 500);
  return () => {
    clearTimeout(timer);
  };
}, [hovered]);

编辑 pedantic-flower-wsp3z


推荐阅读