繁体   English   中英

如何禁用 mapbox 中的事件侦听器?

[英]How to disable an event listener in mapbox?

我正在尝试使用 React 上的 Mapbox 控制层上的事件侦听器。 map.off 应该可以解决这个问题,但它不会删除图层中的 onclick 事件。 https://docs.mapbox.com/mapbox-gl-js/api/map/#map#off

但是我做错了什么,所以我无法删除该事件。 这是我到目前为止所做的...

要添加我这样做的事件

map.on('click', 'building_footprints_click', addBuildingPopUp)

并尝试删除它我尝试过:

map.off('click', 'building_footprints_click', addBuildingPopUp);

map.off('click', 'building_footprints_click');

map.off('click', addBuildingPopUp);

但他们都没有工作。 我读到我必须发送到关闭事件的实例。 所以我试图:

let event = map.on('click', 'building_footprints_click', addBuildingPopUp)

以及与上面相同的三个关闭操作,但它们也不起作用

map.off('click', 'building_footprints_click', event);

map.off('click', 'building_footprints_click');

map.off('click', event);

还有监听器 function,我试过:

const addBuildingPopUp = (e) => {} 

and 
function addBuildingPopUp (e) {} 

and 
let addBuildingPopUp = function building (e) {}

这是一个基本的 Stackblitz,其中包含一个非工作示例 function https://stackblitz.com/edit/react-5maykf?file=src/App.js

https://react-5maykf.stackblitz.io/

我检查了您的 stackblitz 代码,并相应地使用评论更新了工作答案。 如果您对此有任何疑问,请告诉我

https://stackblitz.com/edit/react-mqjjkg?devtoolsheight=33&file=src/App.js

根据您的stackblitz ,我可以看到问题在于您正在尝试注销不再存在的 function。

对于 mapbox,您需要注册和注销相同的 function。 我的意思是map.on('mousemove', f1)map.off('mousemove', f1)你需要确保 f1 保持不变。

让我解释一下,每当一个 react 组件渲染时,它都会在其主体内重新创建所有变量,除非它是 state 变量的一部分,因为 function addBuildingPopUp是在每次渲染时创建的 mapboxgl 不会取消注册事件。

您需要做的唯一更改是确保addBuildingPopUp保持不变,您应该在 React 组件外部定义。

如果您使用 React,只需将处理程序存储在 useRef 中,瞧,一切都会正常工作, 这是类似的情况和建议的解决方案

这是解决方案的代码:

  const handleClickRef = useRef(handleClick)
  handleClickRef.current = handleClick
  map.on('mousedown', 'layer-id', handleClickRef.current)
  map.off('mousedown', 'layer-id', handleClickRef.current)

您传递给 mapbox 事件侦听器的函数必须完全相同。 每次组件在 react 中渲染时,javascript 都会将 function(尽管它保持不变)识别为新声明的 function。 因此,mapbox 将“关闭”一个不存在事件的侦听器,因为它是一个从未存在过的 function。 要解决它,你必须使用 React “useCallback”。 它确保功能在组件存在的过程中保持不变

export default function MapListeners() {
  const mode = useRecoilValue(interactivityMode);
  const setModal = useSetRecoilState(modalState);

  const removeListeners = () => {
    cuMap.off("click", setAddBeaconModal);
  };

  const setAddBeaconModal = useCallback(
    // useCallback ensures the functions stays identical
    (e: mapboxgl.MapMouseEvent & mapboxgl.EventData) => {
      // const coordinates = e.lngLat;

      setModal({
        key: AddBeaconModal.toString(),
        body: {
          component: AddBeaconModal,
          props: { word: "irgendwas", title: "Irrr" },
        },
        title: "Add Beacon",
      });
    },
    []
  );

  const setMapListeners = () => {
    removeListeners();

    switch (mode) {
      case "add":
        cuMap.on("click", setAddBeaconModal);
        break;
      case "lock":
        break;
      default:
    }
  };

  useEffect(setMapListeners, [mode]);

  return null;
}

我已经在 React 中完成了。 我尝试了几天来做到这一点。 所以在我的情况下,我想删除一个点击监听器,它会添加一些自定义标记。 这是我的做法(用于测试):

Attributes in File

const map = useRef(null);

map.current.on('click', (event) => addMarkerOnClick(event));
setTimeout(() => {
  console.log("Disabled")
  map.current.off('click', (event) => addMarkerOnClick(event));
}, 5000)

以上是我最初的代码,它不会工作。

    map.current.on('click', addMarkerOnClick);
    setTimeout(() => {
      console.log("Disabled")
      map.current.off('click', addMarkerOnClick);
    }, 5000)

这就是解决方案。

对于没有 React 的用户,我建议这样做:

// Attributes
let map = null

    map.on('click', addMarkerOnClick);
    setTimeout(() => {
      console.log("Disabled")
      map.off('click', addMarkerOnClick);
    }, 5000)

我今天早上遇到了类似的问题,所以我会插话。 我最终采取的解决方案是将传递给 map.on 和 map.off 的 function 存储在带有空括号的 useCallback 挂钩中。 工作起来很有魅力!

我不知道你在写这个问题时是否打错了,但你写了

map.on('click', 'building_footprints_click', addBuildingPop**UP**);
map.off('click', 'building_footprints_click', addBuildingPop**Up**); 

注意到 function 名称的大小写不同了吗?

这种语法是正确的,它是你应该使用的

如果问题是由于拼写错误,我建议使用 linter 来避免这种情况

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM