延迟反应onMouseOver事件

时间:2018-05-22 11:37:38

标签: javascript reactjs events javascript-events mouseevent

我有一个元素列表,当悬停其中一个元素时,我想改变我的状态。

<ListElement onMouseOver={() => this.setState({data})}>Data</ListElement>

不幸的是,如果我将鼠标移到列表上,我的状态会快速连续几次变化。我想延迟改变状态,以便在被解雇之前等待半秒钟。有办法吗?

5 个答案:

答案 0 :(得分:1)

您可以使用onMouseEnteronMouseLeavesetTimeout的组合将事件延迟500毫秒。

请记住,数据的状态更新可以由父组件进行管理并作为道具传递。

import React, { useState } from 'react'

const ListElement = () => {
    const [data, setData] = useState(null)
    const [delayHandler, setDelayHandler] = useState(null)

    const handleMouseEnter = event => {
        setDelayHandler(setTimeout(() => {
            const yourData = // whatever your data is

            setData(yourData)
        }, 500))
    }

    const handleMouseLeave = () => {
        clearTimeout(delayHandler)
    }

    return (
        <div
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}
        >
            I have a delayed event handler
        </div>
    )
}

export default ListElement

答案 1 :(得分:0)

您可以将debounce用作专用包,也可以从lodash等处获取:

  

用于实现仅在重复操作完成后才会发生的行为。

const debounce = require('debounce');

class YourComponent extends Component {
  constructor(props) {
    super(props);

    this.debouncedMouseOver = debounce(handleMouseOver, 200);
  }

  handleMouseOver = data => this.setState({ data });

  render() {
    const data = [];
    return <ListElement onMouseOver={() => this.debouncedMouseOver(data)}>Data</ListElement>;
  }
}

答案 2 :(得分:0)

您可以创建一个方法,在匹配特殊要求时触发500 ms事件。

在另一个例子中,它在/** * Hold the descriptor to the setTimeout */ protected timeoutOnMouseOver = false; /** * Method which is going to trigger the onMouseOver only once in Xms */ protected mouseOverTreatment(data) { // If they were already a programmed setTimeout // stop it, and run a new one if (this.timeoutOnMouseOver) { clearTimeout(this.timeoutOnMouseOver); } this.timeoutOnMouseOver = setTimeout(() => { this.setState(data); this.timeoutOnMouseOver = false; }, 500); } 之后触发。

{{1}}

答案 3 :(得分:0)

debounce 如果您想在时间范围内限制操作,则始终是答案。

实现简单,无需外部库。

实施:

type Fnc = (...args: any[]) => void;

// default 300ms delay
export function debounce<F extends Fnc>(func: F, delay = 300) {
  type Args = F extends (...args: infer P) => void ? P : never;
  let timeout: any;
  return function (this: any, ...args: Args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

用法:

...

/** any action you want to debounce */
function foo(
    data: any, 
    event: React.MouseEvent<HTMLDivElement, MouseEvent>
): void {
    this.setState({data}
}

const fooDebounced = debounce(foo, 500);

<ListElement onMouseOver={fooDebounced.bind(null, data)}>
    Data
</ListElement>
...

您实际上不必bind一个函数,但如果您循环访问多个元素以避免为每个元素初始化一个新函数,这是一个好习惯。

答案 4 :(得分:0)

我可能有点晚了,但我想使用 Lodash debounce 添加上面的一些答案。对方法进行去抖动时,debounce 函数可让您根据某个事件取消对方法的调用。参见功能组件示例:

const [isHovered, setIsHovered] = React.useState(false)

const debouncedHandleMouseEnter = debounce(() => setIsHovered(true), 500)

const handlOnMouseLeave = () => {
  setIsHovered(false)
  debouncedHandleMouseEnter.cancel()
}

return (
  <div
    onMouseEnter={debouncedHandleMouseEnter}
    onMouseLeave={handlOnMouseLeave}
  >
   ... do something with isHovered state...
  </div>
)

此示例让您仅在用户在您的元素中悬停 500 毫秒后才调用您的函数,如果鼠标离开该元素,则调用将被取消。