网站搜索

javascript - onPointerOver 和 onPointerOut 检测所有子元素


问题是我在每个子元素上都触发了onPointerOver和onPointerOut,但我需要它在一个公共组上触发,因为那样组件就不会被重新渲染得太频繁。

这里有一个组,现在当我移动鼠标光标时,组件会被重绘很多次,我希望当我移动鼠标光标并移开时,我的状态只改变一次。

这一点正在改变,但事实是我的头由许多InstancedMesh组成,结果我的头所组成的每个方块的状态都会发生变化。

我如何让这只对整个组生效,也就是说,当我将光标悬停时,它只对整个组作出反应,而不是对单个方块作出反应?

沙盒

    <group
      position={position}
      onPointerOver={(e) => {
        e.stopPropagation();  
        handlePointerOver(e); 
      }}
      onPointerOut={(e) => {
        e.stopPropagation();
        handlePointerOut(e);
      }}
    >
      <Head scale={scale} isVisibleGrid={isVisibleGrid} position={scaledPosition(0, 24, 0)} />

    </group>
  const handlePointerOver = (e: ThreeEvent<PointerEvent>) => {
    setIsVisibleGrid(true);
    e.stopPropagation();
  };

  const handlePointerOut = (e: ThreeEvent<PointerEvent>) => {
    setIsVisibleGrid(false);
    e.stopPropagation();
  };

答案#1

捕获阶段事件在这里可能有用

下面的示例代码展示了相同的内容。该代码使用点击事件仅作演示用途。

App.js

export default function App() {
  return (
    <>
      <div
        onClickCapture={(e) => {
          console.log('Parent captured');
          e.stopPropagation();
        }}
      >
        Parent
        <br />
        <Child />
      </div>
    </>
  );
}

function Child() {
  return <div onClick={(e) => console.log('Child listened')}>Child</div>;
}

测试运行

应用加载时

点击文本 子项

控制台日志生成如下:

// Parent captured

观察:

尽管点击事件已经在子组件中处理过,但在点击它时该处理程序没有触发。这是因为父组件中捕获了点击事件。它捕获了点击事件。此外,父组件还阻止了事件传播。由于事件传播在父组件中被停止,因此它不会传播到子组件。