如何防止 React-Leaflet Map 的子节点上的事件冒泡

IT技术 javascript reactjs dom leaflet react-leaflet
2021-05-21 13:27:17

我有一个React-Leaflet地图,我正在渲染div里面。

出于某种原因,与 div 的内容交互会导致下面的地图做出响应(例如:双击将缩放地图,拖动将平移地图) - 即使我正在调用e.stopPropagation()附加到 div 的处理程序。

据我了解,调用stopPropagation()应该防止 DOM 事件到达地图本身。

为什么看起来stopPropagation()被忽略了?

我怎样才能在地图内渲染一个 div而不让它的事件冒泡到地图本身?

这是一个显示问题的示例代码笔

import { Map, TileLayer } from 'react-leaflet';

const MyMap = props => (
  <Map zoom={13} center={[51.505, -0.09]}>
    <TileLayer url={"http://{s}.tile.osm.org/{z}/{x}/{y}.png"} />

    {/* 
          HOW do I get this div to NOT pass it's events down to the map?!?! 
          Why does e.stopPropagation() appear to not work?
    */}
    <div 
      id="zone"
      onClick={e => e.stopPropagation()}
      onMouseDown={e => e.stopPropagation()}
      onMouseUp={e => e.stopPropagation()}
    >
      <p>Double-click or click and drag inside this square</p>
      <p>Why does the map zoom/pan?</p>
    </div>

  </Map>
);

ReactDOM.render(<MyMap />, document.getElementById('root'));
1个回答

对于传单地图,请改用L.DomEvent.disableClickPropagation

添加stopPropagation到元素的'click''doubleclick''mousedown''touchstart'事件。

例子

function MyMap() {
  return (
    <div>
      <Map zoom={13} center={[51.505, -0.09]}>
        <TileLayer url={"http://{s}.tile.osm.org/{z}/{x}/{y}.png"} />
        <MyInfo />
      </Map>
    </div>
  );
}

在哪里

function MyInfo() {
  const divRef = useRef(null);

  useEffect(() => {
    L.DomEvent.disableClickPropagation(divRef.current);
  });

  return (
    <div ref={divRef} id="zone">
      <p>Double-click or click and drag inside this square</p>
      <p>Why does the map zoom/pan?</p>
    </div>
  );
}

更新代码笔

替代选项

阻止 div 元素传播到地图事件的另一种选择是将 div放在地图元素之外:

<div>
  <Map zoom={13} center={[51.505, -0.09]}>
    <TileLayer url={"http://{s}.tile.osm.org/{z}/{x}/{y}.png"} />
  </Map>
  <MyInfo />
</div>

在哪里

function MyInfo() {
  return (
    <div id="zone">
      <p>Double-click or click and drag inside this square</p>
      <p>Why does the map zoom/pan?</p>
    </div>
  );
}